mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-30 05:35:31 +00:00
792 lines
18 KiB
C++
792 lines
18 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||
*
|
||
* The contents of this file are subject to the Netscape Public License
|
||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||
* compliance with the NPL. You may obtain a copy of the NPL at
|
||
* http://www.mozilla.org/NPL/
|
||
*
|
||
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||
* for the specific language governing rights and limitations under the
|
||
* NPL.
|
||
*
|
||
* The Initial Developer of this code under the NPL is Netscape
|
||
* Communications Corporation. Portions created by Netscape are
|
||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||
* Reserved.
|
||
*/
|
||
|
||
#include "CFontReference.h"
|
||
|
||
#include <Printing.h>
|
||
|
||
#include "uprefd.h"
|
||
#include "xp_hash.h"
|
||
#include "xp_mem.h"
|
||
#include "lo_ele.h"
|
||
|
||
#include "FontTypes.h"
|
||
#include "shist.h"
|
||
|
||
#include "resgui.h"
|
||
|
||
// Set this to 1 to force WebFont lookup instead of native font lookup
|
||
#define TEST_NATIVE_DISPLAYER 0
|
||
|
||
#if TEST_NATIVE_DISPLAYER
|
||
#include "mcfp.h"
|
||
#endif
|
||
|
||
#include "libi18n.h"
|
||
#include "UPropFontSwitcher.h"
|
||
#include "UFixedFontSwitcher.h"
|
||
#include "UUTF8TextHandler.h"
|
||
|
||
#define WEIGHT_BOLD 700
|
||
#define WEIGHT_NORMAL 400
|
||
|
||
class NameList
|
||
{
|
||
public:
|
||
NameList(char *list);
|
||
~NameList();
|
||
|
||
Boolean Empty();
|
||
void Next();
|
||
char *Current();
|
||
|
||
private:
|
||
char *list, *name;
|
||
int start, next;
|
||
};
|
||
|
||
NameList::NameList(char *list)
|
||
{
|
||
int length = strlen(list);
|
||
|
||
this->list = list;
|
||
start = next = 0;
|
||
|
||
|
||
if (length > 0)
|
||
{
|
||
name = new char[length + 1];
|
||
this->Next();
|
||
}
|
||
else
|
||
{
|
||
name = NULL;
|
||
}
|
||
}
|
||
|
||
NameList::~NameList()
|
||
{
|
||
if (name != NULL)
|
||
delete[] name;
|
||
}
|
||
|
||
char *NameList::Current()
|
||
{
|
||
if (Empty())
|
||
return NULL;
|
||
|
||
return name;
|
||
}
|
||
|
||
Boolean NameList::Empty()
|
||
{
|
||
return list == NULL || list[start] == '\0';
|
||
}
|
||
|
||
void NameList::Next()
|
||
{
|
||
start = next;
|
||
|
||
if (Empty())
|
||
return;
|
||
|
||
// skip over leading whitespace and commas to find the start of the name
|
||
while (list[start] != '\0' && (list[start] == ',' || isspace(list[start])))
|
||
{
|
||
start += 1;
|
||
}
|
||
|
||
// find the end of the name
|
||
next = start;
|
||
while(list[next] != '\0' && list[next] != ',')
|
||
{
|
||
if (list[next] == '"' || list[next] == '\'')
|
||
{
|
||
char final = list[next];
|
||
|
||
// find the matching quote
|
||
next += 1;
|
||
while (list[next] != '\0' && list[next] != final)
|
||
{
|
||
next += 1;
|
||
}
|
||
|
||
// if list[next] is null, there was no matching quote, so bail
|
||
if (list[next] == '\0')
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
next += 1;
|
||
}
|
||
|
||
// strip off trailing whitespace
|
||
int end = next - 1;
|
||
|
||
while (end >= start && isspace(list[end]))
|
||
{
|
||
end -= 1;
|
||
}
|
||
|
||
// copy what's between start and end into name
|
||
int src = start;
|
||
int dst = 0;
|
||
|
||
// if it's quoted, strip off the quotes
|
||
if ((list[start] == '"' || list[start] == '\'') && list[end] == list[start])
|
||
{
|
||
src += 1;
|
||
end -= 1;
|
||
}
|
||
|
||
// copy the characters from src to end into the name
|
||
while (src <= end)
|
||
{
|
||
name[dst++] = list[src++];
|
||
}
|
||
|
||
name[dst] = '\0';
|
||
}
|
||
|
||
void FE_ReleaseTextAttrFeData(MWContext * /* context */, LO_TextAttr *attr)
|
||
{
|
||
CFontReference *fontReference = (CFontReference *) attr->FE_Data;
|
||
|
||
if (fontReference != NULL)
|
||
delete fontReference;
|
||
}
|
||
|
||
short CFontReference::GetScaledTextSize(short size, short attrSize)
|
||
{
|
||
short scaledSize;
|
||
|
||
if ( attrSize < 1 )
|
||
attrSize = 1;
|
||
else if ( attrSize > 7 )
|
||
attrSize = 7;
|
||
|
||
// <20> Houck's font table from WINFE
|
||
switch ( attrSize )
|
||
{
|
||
case 0: scaledSize = size / 2 ; break;
|
||
case 1: scaledSize = 7 * size / 10 ; break;
|
||
case 2: scaledSize = 85 * size / 100 ; break;
|
||
case 3: scaledSize = size ; break;
|
||
case 4: scaledSize = 12 * size / 10 ; break;
|
||
case 5: scaledSize = 3 * size / 2 ; break;
|
||
case 6: scaledSize = 2 * size ; break;
|
||
case 7: scaledSize = 3 * size ; break;
|
||
}
|
||
|
||
// should this test be at a higher level?
|
||
if ( scaledSize < 9 ) // looks bad at anything lower
|
||
scaledSize = 9;
|
||
|
||
return scaledSize;
|
||
}
|
||
|
||
CFontReference *CFontReference::GetFontReference(const CCharSet *charSet, LO_TextAttr* attr, MWContext *context, Boolean underlineLinks)
|
||
{
|
||
CFontReference *result = NULL;
|
||
|
||
if (attr->FE_Data != NULL)
|
||
{
|
||
result = (CFontReference *) attr->FE_Data;
|
||
|
||
result->SynchToPort(qd.thePort);
|
||
|
||
return result;
|
||
}
|
||
|
||
for (NameList list(attr->font_face); !list.Empty(); list.Next())
|
||
{
|
||
|
||
result = CWebFontReference::LookupWebFont(list.Current(), charSet, attr, context, underlineLinks);
|
||
|
||
if (result != NULL)
|
||
goto cache_result;
|
||
|
||
result = CNativeFontReference::LookupNativeFont(list.Current(), charSet, attr, underlineLinks);
|
||
|
||
if (result != NULL)
|
||
goto cache_result;
|
||
|
||
result = CNativeFontReference::LookupGenericFont(list.Current(), charSet, attr, underlineLinks);
|
||
|
||
if (result != NULL)
|
||
goto cache_result;
|
||
}
|
||
|
||
// if we get this far, we don't have any matching fonts
|
||
// just return the default font for the character set.
|
||
|
||
short fontID;
|
||
|
||
if ( attr->fontmask & LO_FONT_FIXED )
|
||
fontID = charSet->fFixedFontNum;
|
||
else
|
||
fontID = charSet->fPropFontNum;
|
||
|
||
result = new CNativeFontReference(fontID, charSet, attr, underlineLinks);
|
||
|
||
cache_result:
|
||
attr->FE_Data = (void *) result;
|
||
return result;
|
||
}
|
||
|
||
CFontReference::CFontReference(const CCharSet *charSet, const LO_TextAttr *attr)
|
||
{
|
||
fIsGetFontInfoDirty = true;
|
||
|
||
fMode = srcOr;
|
||
|
||
if (attr->point_size == 0)
|
||
{
|
||
short textSize;
|
||
|
||
if (attr->fontmask & LO_FONT_FIXED)
|
||
textSize = charSet->fFixedFontSize;
|
||
else
|
||
textSize = charSet->fPropFontSize;
|
||
|
||
fSize = GetScaledTextSize(textSize, attr->size);
|
||
}
|
||
else
|
||
{
|
||
fSize = attr->point_size;
|
||
}
|
||
}
|
||
|
||
CFontReference::~CFontReference()
|
||
{
|
||
// **** is there anything to do here?
|
||
}
|
||
|
||
void CNativeFontReference::Apply()
|
||
{
|
||
if ( qd.thePort->txFont != fFont )
|
||
::TextFont( fFont );
|
||
|
||
if ( qd.thePort->txSize != fSize )
|
||
::TextSize( fSize );
|
||
|
||
if ( qd.thePort->txFace != fStyle )
|
||
::TextFace( fStyle );
|
||
|
||
if ( qd.thePort->txMode != fMode )
|
||
::TextMode( fMode );
|
||
}
|
||
|
||
CFontReference *CNativeFontReference::LookupNativeFont(char *fontName, const CCharSet *charSet, const LO_TextAttr *attr,
|
||
Boolean underlineLinks)
|
||
{
|
||
short fontID;
|
||
CStr255 pName(fontName);
|
||
|
||
::GetFNum(pName, &fontID);
|
||
|
||
if (fontID == 0)
|
||
{
|
||
|
||
/*
|
||
Font ID 0 is the system font. Did we get this
|
||
ID because the named font doesn't exist, or
|
||
because we asked for the system font by name?
|
||
*/
|
||
static CStr255 systemFontName;
|
||
|
||
if (systemFontName[0] == 0)
|
||
::GetFontName(0, systemFontName);
|
||
|
||
if (pName != systemFontName)
|
||
return NULL;
|
||
}
|
||
|
||
return new CNativeFontReference(fontID, charSet, attr, underlineLinks);
|
||
}
|
||
|
||
CFontReference *CNativeFontReference::LookupGenericFont(char *fontName, const CCharSet *charSet, const LO_TextAttr *attr,
|
||
Boolean underlineLinks)
|
||
{
|
||
struct GenericFontFamily
|
||
{
|
||
char *genericName;
|
||
char *nativeName;
|
||
};
|
||
|
||
// NOTE: These need to be in the same order as they are
|
||
// in the resource.
|
||
static GenericFontFamily genericNames[] =
|
||
{
|
||
{"serif", NULL},
|
||
{"sans-serif", NULL},
|
||
{"cursive", NULL},
|
||
{"fantasy", NULL},
|
||
{"monospace", NULL}
|
||
};
|
||
|
||
static const int genericNameCount = sizeof(genericNames) / sizeof(GenericFontFamily);
|
||
|
||
for (int nameIndex = 0; nameIndex < genericNameCount; nameIndex += 1)
|
||
{
|
||
if (!XP_STRCASECMP( fontName, genericNames[nameIndex].genericName))
|
||
{
|
||
if (genericNames[nameIndex].nativeName == NULL)
|
||
{
|
||
Str255 nativeName;
|
||
|
||
::GetIndString(nativeName, GENERIC_FONT_NAMES_RESID, nameIndex + 1);
|
||
|
||
XP_ASSERT(nativeName[0] != 0);
|
||
|
||
// allocate memory for a copy of the name
|
||
genericNames[nameIndex].nativeName = (char *) XP_ALLOC(nativeName[0] + 1);
|
||
|
||
// bail if no memory for the name
|
||
if (genericNames[nameIndex].nativeName == NULL)
|
||
return NULL;
|
||
|
||
// copy it as a C string
|
||
strncpy(genericNames[nameIndex].nativeName, (char *) &nativeName[1], nativeName[0]);
|
||
genericNames[nameIndex].nativeName[nativeName[0]] = '\0';
|
||
}
|
||
|
||
return CNativeFontReference::LookupNativeFont(genericNames[nameIndex].nativeName, charSet, attr, underlineLinks);
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
CNativeFontReference::CNativeFontReference(short font, const CCharSet *charSet, const LO_TextAttr *attr,
|
||
Boolean /* underlineLinks */) :
|
||
CFontReference(charSet, attr)
|
||
{
|
||
fFont = font;
|
||
fStyle = 0;
|
||
|
||
if ((charSet->fCSID & MULTIBYTE) != SINGLEBYTE)
|
||
{
|
||
switch(charSet->fCSID)
|
||
{
|
||
case CS_UTF8:
|
||
fTextHandler = UUTF8TextHandler::Instance();
|
||
break;
|
||
|
||
/*
|
||
// **** really want handlers for all multi-byte text
|
||
// use system for now...
|
||
case CS_SJIS:
|
||
fTextHandler = SJISTextHandler::Instance();
|
||
break;
|
||
|
||
default:
|
||
fTextHandler = MBTextHandler::Instance();
|
||
*/
|
||
default:
|
||
fTextHandler = NULL;
|
||
}
|
||
|
||
if (attr->fontmask & LO_FONT_FIXED)
|
||
fFontSwitcher = UFixedFontSwitcher::Instance();
|
||
else
|
||
fFontSwitcher = UPropFontSwitcher::Instance();
|
||
}
|
||
else
|
||
{
|
||
fTextHandler = NULL;
|
||
fFontSwitcher = NULL;
|
||
}
|
||
|
||
if (attr->font_weight >= WEIGHT_BOLD || (attr->fontmask & LO_FONT_BOLD) != 0)
|
||
fStyle |= bold;
|
||
|
||
if (attr->fontmask & LO_FONT_ITALIC)
|
||
fStyle |= italic;
|
||
|
||
if (attr->attrmask & LO_ATTR_UNDERLINE)
|
||
fStyle |= underline;
|
||
}
|
||
|
||
CNativeFontReference::~CNativeFontReference()
|
||
{
|
||
// **** Anything interesting to do here?
|
||
}
|
||
|
||
void CNativeFontReference::DrawText(int x, int y, char *text, int start, int end)
|
||
{
|
||
::MoveTo(x, y);
|
||
|
||
if (fTextHandler != NULL)
|
||
fTextHandler->DrawText(fFontSwitcher, &text[start], end - start + 1);
|
||
else
|
||
::DrawText(text, start, end - start + 1);
|
||
|
||
}
|
||
|
||
short CNativeFontReference::TextWidth(char *text, int firstByte, int byteCount)
|
||
{
|
||
if (fTextHandler != NULL)
|
||
return fTextHandler->TextWidth(fFontSwitcher, &text[firstByte], byteCount);
|
||
else
|
||
return ::TextWidth(text, firstByte, byteCount);
|
||
}
|
||
|
||
short CNativeFontReference::MeasureText(char *text, int firstByte, int byteCount, short* charLocs)
|
||
{
|
||
if (fTextHandler != NULL)
|
||
return 0;
|
||
else
|
||
{
|
||
text = &text[firstByte];
|
||
::MeasureText(byteCount, text, charLocs);
|
||
|
||
// remove null chars widths
|
||
short widthOffset = 0;
|
||
short nullCharWidth = 0;
|
||
for (int i = 1; i <= byteCount; i ++)
|
||
{
|
||
if (text[i-1] == '\0')
|
||
{
|
||
if (nullCharWidth == 0)
|
||
{
|
||
nullCharWidth = charLocs[i] - charLocs[i-1];
|
||
if (nullCharWidth == 0)
|
||
break;
|
||
}
|
||
widthOffset += nullCharWidth;
|
||
}
|
||
charLocs[i] -= widthOffset;
|
||
}
|
||
|
||
return byteCount;
|
||
}
|
||
}
|
||
|
||
void CNativeFontReference::GetFontInfo(FontInfo *fontInfo)
|
||
{
|
||
if (fIsGetFontInfoDirty)
|
||
{
|
||
if (fTextHandler != NULL)
|
||
fTextHandler->GetFontInfo(fFontSwitcher, &fCachedFontInfoValues);
|
||
else
|
||
::GetFontInfo(&fCachedFontInfoValues);
|
||
|
||
fIsGetFontInfoDirty = false;
|
||
}
|
||
|
||
*fontInfo = fCachedFontInfoValues;
|
||
}
|
||
|
||
FontBrokerHandle CWebFontReference::sBroker = NULL;
|
||
FontBrokerUtilityHandle CWebFontReference::sUtility = NULL;
|
||
XP_HashTable CWebFontReference::sPortHash = NULL;
|
||
|
||
char *CWebFontReference::sCatalogPath = NULL;
|
||
|
||
#define REQUIRED_GUTS_PATH "/usr/local/netscape/RequiredGuts/"
|
||
|
||
void CWebFontReference::Init()
|
||
{
|
||
jint jresult;
|
||
char *displayerPath;
|
||
Str31 essentialFiles, dynamicFonts, dynamicFontCatalog;
|
||
FontBrokerDisplayerHandle brokerDisplayer;
|
||
#if TEST_NATIVE_DISPLAYER
|
||
FontDisplayerHandle nativeDisplayer;
|
||
#endif
|
||
|
||
sPortHash = XP_HashTableNew(10, PortHash, PortCompFunction);
|
||
|
||
sBroker = NF_FontBrokerInitialize();
|
||
if (sBroker == NULL)
|
||
{
|
||
// error?
|
||
return;
|
||
}
|
||
|
||
brokerDisplayer = (FontBrokerDisplayerHandle) nffbc_getInterface(sBroker, &nffbp_ID, NULL);
|
||
if(brokerDisplayer == NULL)
|
||
{
|
||
// error?
|
||
return;
|
||
}
|
||
|
||
#if TEST_NATIVE_DISPLAYER
|
||
nativeDisplayer = (FontDisplayerHandle) cfpFactory_Create(NULL, brokerDisplayer);
|
||
if (nativeDisplayer != NULL)
|
||
{
|
||
nffbp_RegisterFontDisplayer(brokerDisplayer, nativeDisplayer, NULL);
|
||
}
|
||
#endif
|
||
|
||
sUtility = (FontBrokerUtilityHandle) nffbc_getInterface(sBroker, &nffbu_ID, NULL);
|
||
if (sUtility == NULL)
|
||
{
|
||
// error?
|
||
return;
|
||
}
|
||
|
||
::GetIndString(essentialFiles, 14000, 1);
|
||
::GetIndString(dynamicFonts, 14000, 3);
|
||
::GetIndString(dynamicFontCatalog, 14000, 4);
|
||
|
||
XP_ASSERT(essentialFiles[0] != 0 && dynamicFonts[0] != 0 && dynamicFontCatalog[0] != 0);
|
||
|
||
// "+ 4" is for three colons plus the null
|
||
sCatalogPath = (char *) XP_ALLOC(essentialFiles[0] + dynamicFonts[0] + dynamicFontCatalog[0] + 4);
|
||
if (sCatalogPath != NULL)
|
||
{
|
||
// Build ":Essential Files:DynamicFonts:Dynamic Font Catalog"
|
||
strcpy(sCatalogPath, PATH_SEPARATOR_STR);
|
||
strncat(sCatalogPath, (char *) &essentialFiles[1], essentialFiles[0]);
|
||
strcat(sCatalogPath, PATH_SEPARATOR_STR);
|
||
strncat(sCatalogPath, (char *) &dynamicFonts[1], dynamicFonts[0]);
|
||
strcat(sCatalogPath, PATH_SEPARATOR_STR);
|
||
strncat(sCatalogPath, (char *) &dynamicFontCatalog[1], dynamicFontCatalog[0]);
|
||
|
||
// Don't care if this fails, file will be created when we save it.
|
||
jresult = nffbu_LoadCatalog(sUtility, sCatalogPath, NULL);
|
||
}
|
||
|
||
// "+ 2" is for one slash and the null
|
||
displayerPath = (char *) XP_ALLOC(sizeof(REQUIRED_GUTS_PATH) + dynamicFonts[0] + 2);
|
||
if (displayerPath != NULL)
|
||
{
|
||
// Build REQUIRED_GUTS_PATH "Dynamic Fonts/"
|
||
strcpy(displayerPath, REQUIRED_GUTS_PATH);
|
||
strncat(displayerPath, (char *) &dynamicFonts[1], dynamicFonts[0]);
|
||
strcat(displayerPath, DIRECTORY_SEPARATOR_STR);
|
||
|
||
// Result is number of displayers created, we don't really care
|
||
jresult = nffbp_ScanForFontDisplayers(brokerDisplayer, displayerPath, NULL);
|
||
|
||
XP_FREE(displayerPath);
|
||
}
|
||
}
|
||
|
||
void CWebFontReference::Finish()
|
||
{
|
||
jint result;
|
||
|
||
if (sCatalogPath != NULL)
|
||
{
|
||
result = nffbu_SaveCatalog(sUtility, sCatalogPath, NULL);
|
||
XP_FREE(sCatalogPath);
|
||
sCatalogPath = NULL;
|
||
}
|
||
}
|
||
|
||
// Make sure the rc's port is port...
|
||
void CWebFontReference::SynchToPort(GrafPtr port)
|
||
{
|
||
struct rc_data rcd = nfrc_GetPlatformData(fRenderingContext, NULL);
|
||
|
||
if (rcd.t.directRc.port != port)
|
||
{
|
||
rcd.t.directRc.port = port;
|
||
nfrc_SetPlatformData(fRenderingContext, &rcd, NULL);
|
||
}
|
||
|
||
}
|
||
|
||
// It's not clear to me that this is good hash, but it's fast!
|
||
uint32 CWebFontReference::PortHash(const void *port)
|
||
{
|
||
return (uint32) port;
|
||
}
|
||
|
||
// Should I look at the port fields if the addresses aren't equal?
|
||
int CWebFontReference::PortCompFunction(const void *port1, const void *port2)
|
||
{
|
||
return port1 != port2;
|
||
}
|
||
|
||
RenderingContextHandle CWebFontReference::GetCachedRenderingContext(GrafPtr port)
|
||
{
|
||
RenderingContextHandle rc = (RenderingContextHandle) XP_Gethash(sPortHash, port, NULL);
|
||
|
||
if (rc == NULL)
|
||
{
|
||
void *rcArgs[1];
|
||
|
||
rcArgs[0] = port;
|
||
rc = nffbu_CreateRenderingContext(sUtility, NF_RC_DIRECT, 0, rcArgs, 1, NULL);
|
||
|
||
if (rc != NULL)
|
||
{
|
||
XP_Puthash(sPortHash, port, rc);
|
||
}
|
||
// error?
|
||
}
|
||
|
||
return rc;
|
||
}
|
||
|
||
CFontReference *CWebFontReference::LookupWebFont(char *fontName, const CCharSet *charSet, const LO_TextAttr *attr, MWContext *context, Boolean underlineLinks)
|
||
{
|
||
FontMatchInfoHandle fmi;
|
||
RenderingContextHandle renderingContext;
|
||
WebFontHandle webFont;
|
||
|
||
char encoding[64]; // Should get the "64" from a header file...
|
||
char *charset = NULL; // Is this the right value?
|
||
int weight;
|
||
int style = nfStyleNormal;
|
||
int escapement = nfSpacingProportional;
|
||
int underline = nfUnderlineNo;
|
||
int strikeout = nfStrikeOutNo;
|
||
int resolutionX, resolutionY;
|
||
|
||
if (attr->font_weight != 0)
|
||
weight = attr->font_weight;
|
||
else if (attr->fontmask & LO_FONT_BOLD)
|
||
weight = WEIGHT_BOLD;
|
||
else
|
||
weight = WEIGHT_NORMAL;
|
||
|
||
if (attr->fontmask & LO_FONT_ITALIC)
|
||
style = nfStyleItalic;
|
||
|
||
if (attr->fontmask & LO_FONT_FIXED)
|
||
escapement = nfSpacingMonospaced;
|
||
|
||
if (attr->attrmask & LO_ATTR_UNDERLINE)
|
||
underline = nfUnderlineYes;
|
||
|
||
if ((attr->attrmask & LO_ATTR_ANCHOR) != 0 && underlineLinks)
|
||
underline = nfUnderlineYes;
|
||
|
||
if (attr->attrmask & LO_ATTR_STRIKEOUT)
|
||
strikeout = nfStrikeOutYes;
|
||
|
||
if (context->type == MWContextPrint)
|
||
{
|
||
THPrint hp = CPrefs::GetPrintRecord();
|
||
|
||
if (hp != NULL)
|
||
{
|
||
::PrValidate(hp);
|
||
|
||
resolutionX = (**hp).prInfo.iHRes;
|
||
resolutionY = (**hp).prInfo.iVRes;
|
||
}
|
||
else
|
||
{
|
||
// **** What is a good default in this case?
|
||
resolutionX = 72;
|
||
resolutionY = 72;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
resolutionX = context->XpixelsPerPoint * 72.0;
|
||
resolutionY = context->YpixelsPerPoint * 72.0;
|
||
}
|
||
|
||
INTL_CharSetIDToName(charSet->fCSID, encoding);
|
||
|
||
fmi = nffbu_CreateFontMatchInfo(sUtility, fontName, charset, encoding,
|
||
weight, escapement, style, underline, strikeout,
|
||
resolutionX, resolutionY,
|
||
NULL);
|
||
|
||
if (fmi == NULL)
|
||
{
|
||
// if we can't get an fmi, just bail
|
||
return NULL;
|
||
}
|
||
|
||
// **** Is qd.thePort the right place to get the port from?
|
||
History_entry *he = SHIST_GetCurrent(&context->hist);
|
||
char *url = NULL;
|
||
|
||
if (he != NULL)
|
||
url = he->address;
|
||
|
||
renderingContext = GetCachedRenderingContext(qd.thePort);
|
||
webFont = nffbc_LookupFont(sBroker, renderingContext, fmi, url, NULL);
|
||
|
||
if (webFont == NULL)
|
||
{
|
||
nffbu_LookupFailed(sUtility, context, renderingContext, fmi, NULL);
|
||
nffmi_release(fmi, NULL);
|
||
|
||
return NULL;
|
||
}
|
||
|
||
return new CWebFontReference(webFont, charSet, attr);
|
||
}
|
||
|
||
CWebFontReference::CWebFontReference(WebFontHandle webFont, const CCharSet *charSet, const LO_TextAttr *attr) :
|
||
CFontReference(charSet, attr)
|
||
{
|
||
fRenderingContext = GetCachedRenderingContext(qd.thePort);
|
||
fRenderableFont = nff_GetRenderableFont(webFont, fRenderingContext, fSize, NULL);
|
||
|
||
nff_release(webFont, NULL);
|
||
}
|
||
|
||
CWebFontReference::~CWebFontReference()
|
||
{
|
||
nfrf_release(fRenderableFont, NULL);
|
||
}
|
||
|
||
void CWebFontReference::Apply()
|
||
{
|
||
if ( qd.thePort->txMode != fMode )
|
||
::TextMode( fMode );
|
||
}
|
||
|
||
void CWebFontReference::DrawText(int x, int y, char *text, int start, int end)
|
||
{
|
||
nfrf_DrawText(fRenderableFont, fRenderingContext, x, y, 0, (jbyte*)&text[start], end - start + 1, NULL);
|
||
}
|
||
|
||
short CWebFontReference::TextWidth(char *text, int firstByte, int byteCount)
|
||
{
|
||
jint totalLength;
|
||
jint *charLocs;
|
||
|
||
// **** Do we need to calculate the character count here?
|
||
charLocs = (jint *) XP_ALLOC(byteCount * sizeof(jint));
|
||
|
||
totalLength = nfrf_MeasureText(fRenderableFont, fRenderingContext, 0, (jbyte*)&text[firstByte], byteCount, charLocs, byteCount, NULL);
|
||
|
||
XP_FREE(charLocs);
|
||
return (short) totalLength;
|
||
}
|
||
|
||
void CWebFontReference::GetFontInfo(FontInfo *fontInfo)
|
||
{
|
||
if (fIsGetFontInfoDirty)
|
||
{
|
||
fCachedFontInfoValues.ascent = nfrf_GetFontAscent(fRenderableFont, NULL);
|
||
fCachedFontInfoValues.descent = nfrf_GetFontDescent(fRenderableFont, NULL);
|
||
fCachedFontInfoValues.widMax = nfrf_GetMaxWidth(fRenderableFont, NULL);
|
||
|
||
// **** Can we do better here?
|
||
fontInfo->leading = 0;
|
||
|
||
fIsGetFontInfoDirty = false;
|
||
}
|
||
|
||
*fontInfo = fCachedFontInfoValues;
|
||
}
|