/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: NPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Netscape Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the NPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the NPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsCarbonHelpers.h" #include "nsFontMetricsMac.h" #include "nsDeviceContextMac.h" #include "nsUnicodeFontMappingMac.h" #include "nsUnicodeMappingUtil.h" #include "nsGfxUtils.h" #include "nsFontUtils.h" #define BAD_FONT_NUM -1 nsFontMetricsMac :: nsFontMetricsMac() { mFont = nsnull; mFontNum = BAD_FONT_NUM; mFontMapping = nsnull; } nsFontMetricsMac :: ~nsFontMetricsMac() { if (nsnull != mFont) { delete mFont; mFont = nsnull; } if (mContext) { // Notify our device context that owns us so that it can update its font cache mContext->FontMetricsDeleted(this); mContext = nsnull; } if (mFontMapping) { delete mFontMapping; } } //------------------------------------------------------------------------ NS_IMPL_ISUPPORTS1(nsFontMetricsMac, nsIFontMetrics) NS_IMETHODIMP nsFontMetricsMac::Init(const nsFont& aFont, nsIAtom* aLangGroup, nsIDeviceContext* aCX) { NS_ASSERTION(!(nsnull == aCX), "attempt to init fontmetrics with null device context"); mFont = new nsFont(aFont); mLangGroup = aLangGroup; mContext = aCX; RealizeFont(); TextStyle theStyle; nsFontUtils::GetNativeTextStyle(*this, *mContext, theStyle); StTextStyleSetter styleSetter(theStyle); FontInfo fInfo; GetFontInfo(&fInfo); float dev2app; dev2app = mContext->DevUnitsToAppUnits(); mLeading = NSToCoordRound(float(fInfo.leading) * dev2app); mEmAscent = NSToCoordRound(float(fInfo.ascent) * dev2app); mEmDescent = NSToCoordRound(float(fInfo.descent) * dev2app); mEmHeight = mEmAscent + mEmDescent; mMaxHeight = mEmHeight + mLeading; mMaxAscent = mEmAscent; mMaxDescent = mEmDescent; mMaxAdvance = NSToCoordRound(float(::CharWidth('M')) * dev2app); // don't use fInfo.widMax here mAveCharWidth = NSToCoordRound(float(::CharWidth('x')) * dev2app); mSpaceWidth = NSToCoordRound(float(::CharWidth(' ')) * dev2app); Point frac; frac.h = frac.v = 1; unsigned char x = 'x'; short ascent; if (noErr == ::OutlineMetrics(1, &x, frac, frac, &ascent, 0, 0, 0, 0)) mXHeight = NSToCoordRound(float(ascent) * dev2app); else mXHeight = NSToCoordRound(float(mMaxAscent) * 0.71f); // 0.71 = 5 / 7 return NS_OK; } nsUnicodeFontMappingMac* nsFontMetricsMac::GetUnicodeFontMapping() { if (!mFontMapping) { // we should pass the documentCharset from the nsIDocument level and // the lang attribute from the tag level to here. // XXX hard code to some value till peterl pass them down. nsAutoString langGroup; if (mLangGroup) mLangGroup->ToString(langGroup); else langGroup.Assign(NS_LITERAL_STRING("ja")); nsString lang; mFontMapping = new nsUnicodeFontMappingMac(mFont, mContext, langGroup, lang); } return mFontMapping; } static void MapGenericFamilyToFont(const nsString& aGenericFamily, nsString& aFontFace, ScriptCode aScriptCode) { // the CSS generic names (conversions from the old Mac Mozilla code for now) nsUnicodeMappingUtil* unicodeMappingUtil = nsUnicodeMappingUtil::GetSingleton(); if (unicodeMappingUtil) { nsString* foundFont = unicodeMappingUtil->GenericFontNameForScript( aScriptCode, unicodeMappingUtil->MapGenericFontNameType(aGenericFamily)); if (foundFont) { aFontFace = *foundFont; return; } } NS_ASSERTION(0, "Failed to find a font"); aFontFace.Assign(NS_LITERAL_STRING("Times")); /* // fall back onto hard-coded font names if (aGenericFamily.EqualsIgnoreCase("serif")) { aFontFace.Assign(NS_LITERAL_STRING("Times")); } else if (aGenericFamily.EqualsIgnoreCase("sans-serif")) { aFontFace.Assign(NS_LITERAL_STRING("Helvetica")); } else if (aGenericFamily.EqualsIgnoreCase("cursive")) { aFontFace.Assign(NS_LITERAL_STRING("Apple Chancery")); } else if (aGenericFamily.EqualsIgnoreCase("fantasy")) { aFontFace.Assign(NS_LITERAL_STRING("Gadget")); } else if (aGenericFamily.EqualsIgnoreCase("monospace")) { aFontFace.Assign(NS_LITERAL_STRING("Courier")); } else if (aGenericFamily.EqualsIgnoreCase("-moz-fixed")) { aFontFace.Assign(NS_LITERAL_STRING("Courier")); } */ } struct FontEnumData { FontEnumData(nsIDeviceContext* aDC, nsString& aFaceName, ScriptCode aScriptCode) : mContext(aDC), mFaceName(aFaceName), mScriptCode(aScriptCode) {} nsIDeviceContext* mContext; nsString& mFaceName; ScriptCode mScriptCode; }; static PRBool FontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData) { FontEnumData* data = (FontEnumData*)aData; if (aGeneric) { nsAutoString realFace; MapGenericFamilyToFont(aFamily, realFace, data->mScriptCode); data->mFaceName = realFace; return PR_FALSE; // stop } else { nsAutoString realFace; PRBool aliased; data->mContext->GetLocalFontName(aFamily, realFace, aliased); if (aliased || (NS_OK == data->mContext->CheckFontExistence(realFace))) { data->mFaceName = realFace; return PR_FALSE; // stop } } return PR_TRUE; } void nsFontMetricsMac::RealizeFont() { nsAutoString fontName; nsUnicodeMappingUtil *unicodeMappingUtil; ScriptCode theScriptCode; unicodeMappingUtil = nsUnicodeMappingUtil::GetSingleton (); if (unicodeMappingUtil) { nsAutoString theLangGroupString; if (mLangGroup) mLangGroup->ToString(theLangGroupString); else theLangGroupString.Assign(NS_LITERAL_STRING("ja")); theScriptCode = unicodeMappingUtil->MapLangGroupToScriptCode( NS_ConvertUCS2toUTF8(theLangGroupString).get()); } else theScriptCode = GetScriptManagerVariable (smSysScript); FontEnumData fontData(mContext, fontName, theScriptCode); mFont->EnumerateFamilies(FontEnumCallback, &fontData); nsDeviceContextMac::GetMacFontNumber(fontName, mFontNum); } NS_IMETHODIMP nsFontMetricsMac::Destroy() { mContext = nsnull; return NS_OK; } //------------------------------------------------------------------------ NS_IMETHODIMP nsFontMetricsMac :: GetXHeight(nscoord& aResult) { aResult = mXHeight; return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetSuperscriptOffset(nscoord& aResult) { float dev2app; dev2app = mContext->DevUnitsToAppUnits(); aResult = NSToCoordRound(float(mMaxAscent / 2) - dev2app); return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetSubscriptOffset(nscoord& aResult) { float dev2app; dev2app = mContext->DevUnitsToAppUnits(); aResult = NSToCoordRound(float(mMaxAscent / 2) - dev2app); return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetStrikeout(nscoord& aOffset, nscoord& aSize) { float dev2app; dev2app = mContext->DevUnitsToAppUnits(); aOffset = NSToCoordRound(float(mMaxAscent / 2) - dev2app); aSize = NSToCoordRound(dev2app); return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetUnderline(nscoord& aOffset, nscoord& aSize) { float dev2app; dev2app = mContext->DevUnitsToAppUnits(); aOffset = -NSToCoordRound( dev2app ); aSize = NSToCoordRound( dev2app ); return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetHeight(nscoord &aHeight) { aHeight = mMaxHeight; return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetNormalLineHeight(nscoord &aHeight) { aHeight = mMaxHeight; // on Windows, it's mEmHeight + mLeading (= mMaxHeight on the Mac) return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetLeading(nscoord &aLeading) { aLeading = mLeading; return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetEmHeight(nscoord &aHeight) { aHeight = mEmHeight; return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetEmAscent(nscoord &aAscent) { aAscent = mEmAscent; return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetEmDescent(nscoord &aDescent) { aDescent = mEmDescent; return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetMaxHeight(nscoord &aHeight) { aHeight = mMaxHeight; return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetMaxAscent(nscoord &aAscent) { aAscent = mMaxAscent; return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetMaxDescent(nscoord &aDescent) { aDescent = mMaxDescent; return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetMaxAdvance(nscoord &aAdvance) { aAdvance = mMaxAdvance; return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetAveCharWidth(nscoord &aAveCharWidth) { aAveCharWidth = mAveCharWidth; return NS_OK; } nsresult nsFontMetricsMac :: GetSpaceWidth(nscoord &aSpaceWidth) { aSpaceWidth = mSpaceWidth; return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetFont(const nsFont *&aFont) { aFont = mFont; return NS_OK; } NS_IMETHODIMP nsFontMetricsMac::GetLangGroup(nsIAtom** aLangGroup) { if (!aLangGroup) { return NS_ERROR_NULL_POINTER; } *aLangGroup = mLangGroup; NS_IF_ADDREF(*aLangGroup); return NS_OK; } NS_IMETHODIMP nsFontMetricsMac :: GetWidths(const nscoord *&aWidths) { return NS_ERROR_NOT_IMPLEMENTED; //XXX } NS_IMETHODIMP nsFontMetricsMac :: GetFontHandle(nsFontHandle &aHandle) { // NOTE: the name in the mFont may be a comma-separated list of // font names, like "Verdana, Arial, sans-serif" // If you want to do the conversion again to a Mac font, you'll // have to EnumerateFamilies() to resolve it to an installed // font again. NS_PRECONDITION(mFontNum != BAD_FONT_NUM, "Font metrics have not been initialized"); // We have no 'font handles' on Mac like they have on Windows // so let's use it for the fontNum. aHandle = (nsFontHandle)mFontNum; return NS_OK; }