460 lines
9.7 KiB
C++
460 lines
9.7 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.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 Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
/*
|
|
* fmi.cpp (FontMatchInfoObject.cpp)
|
|
*
|
|
* C++ implementation of the (fmi) FontMatchInfoObject
|
|
*
|
|
* dp Suresh <dp@netscape.com>
|
|
*/
|
|
|
|
|
|
#include "fmi.h"
|
|
|
|
static const char *fmi_attributes[] = {
|
|
nfFmiName,
|
|
nfFmiCharset,
|
|
nfFmiEncoding,
|
|
nfFmiWeight,
|
|
nfFmiPitch,
|
|
nfFmiStyle,
|
|
nfFmiUnderline,
|
|
nfFmiStrikeOut,
|
|
nfFmiResolutionX,
|
|
nfFmiResolutionY,
|
|
};
|
|
|
|
static char fmi_attributes_type[] = {
|
|
FMI_TYPE_CSTRING,
|
|
FMI_TYPE_CSTRING,
|
|
FMI_TYPE_CSTRING,
|
|
FMI_TYPE_JINT,
|
|
FMI_TYPE_JINT,
|
|
FMI_TYPE_JINT,
|
|
FMI_TYPE_JINT,
|
|
FMI_TYPE_JINT,
|
|
FMI_TYPE_JINT,
|
|
FMI_TYPE_JINT,
|
|
};
|
|
|
|
#define MAX_STANDARD_ATTRIBUTES (sizeof(fmi_attributes)/sizeof(*fmi_attributes))
|
|
|
|
FontMatchInfoObject::
|
|
FontMatchInfoObject(const char *iname, const char *icharset,
|
|
const char *iencoding, jint iweight, jint ipitch,
|
|
jint istyle, jint iunderline, jint istrikeOut, jint resX, jint resY)
|
|
: wfList(free_fmi_attr_store), stringRepresentation(NULL),
|
|
stringLen(0), stringMaxLen(0)
|
|
{
|
|
addAttribute(nfFmiName, iname);
|
|
addAttribute(nfFmiCharset, icharset);
|
|
addAttribute(nfFmiEncoding, iencoding);
|
|
addAttribute(nfFmiWeight, iweight);
|
|
addAttribute(nfFmiPitch, ipitch);
|
|
addAttribute(nfFmiStyle, istyle);
|
|
addAttribute(nfFmiUnderline, iunderline);
|
|
addAttribute(nfFmiStrikeOut, istrikeOut);
|
|
addAttribute(nfFmiResolutionX, resX);
|
|
addAttribute(nfFmiResolutionY, resY);
|
|
WF_TRACEMSG( ("NF: Created fmi (%s).", describe()) );
|
|
}
|
|
|
|
FontMatchInfoObject::
|
|
FontMatchInfoObject(const char *reconstructString)
|
|
: wfList(free_fmi_attr_store), stringRepresentation(NULL),
|
|
stringLen(0), stringMaxLen(0)
|
|
{
|
|
reconstruct(reconstructString);
|
|
}
|
|
|
|
FontMatchInfoObject::
|
|
~FontMatchInfoObject()
|
|
{
|
|
WF_TRACEMSG( ("NF: Destroying fmi (%s).", describe()) );
|
|
releaseStringRepresentation();
|
|
}
|
|
|
|
const char ** FontMatchInfoObject::
|
|
ListAttributes()
|
|
{
|
|
return (fmi_attributes);
|
|
}
|
|
|
|
void * FontMatchInfoObject::
|
|
GetValue(const char *attr)
|
|
{
|
|
wfListElement *tmp = head;
|
|
void *value = NULL;
|
|
|
|
if (!attr)
|
|
{
|
|
// Invalid input
|
|
return (NULL);
|
|
}
|
|
|
|
for (; tmp; tmp = tmp->next)
|
|
{
|
|
struct fmi_attr_store *ele = (struct fmi_attr_store *)tmp->item;
|
|
if (ele->attr && !strcmp(ele->attr, attr))
|
|
{
|
|
value = ele->u.genericValue;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (value);
|
|
}
|
|
|
|
jint FontMatchInfoObject::
|
|
IsEquivalent(struct nffmi *fmi)
|
|
{
|
|
void *fmi_value;
|
|
void *this_value;
|
|
for (int i = 0; i < MAX_STANDARD_ATTRIBUTES; i++)
|
|
{
|
|
fmi_value = nffmi_GetValue(fmi, fmi_attributes[i], NULL);
|
|
this_value = GetValue(fmi_attributes[i]);
|
|
if (fmi_attributes_type[i] == FMI_TYPE_CSTRING)
|
|
{
|
|
// FMI_TYPE_CSTRING
|
|
char * fmi_str_value = (char *)fmi_value;
|
|
char * this_str_value = (char *)this_value;
|
|
if (fmi_str_value != NULL && *fmi_str_value != '*' &&
|
|
this_str_value != NULL && *this_str_value != '*' &&
|
|
!strcmp(fmi_str_value, this_str_value))
|
|
{
|
|
// Mismatch
|
|
return (0);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// FMI_TYPE_INT
|
|
#ifdef OSF1
|
|
long fmi_int_value = (long)fmi_value;
|
|
long this_int_value = (long)this_value;
|
|
#else
|
|
int fmi_int_value = (int)fmi_value;
|
|
int this_int_value = (int)this_value;
|
|
#endif
|
|
if (fmi_int_value != 0 && this_int_value != 0
|
|
&& fmi_int_value != this_int_value)
|
|
{
|
|
// Mismatch
|
|
return (0);
|
|
}
|
|
|
|
}
|
|
}
|
|
return (1);
|
|
}
|
|
|
|
|
|
//
|
|
// Check for equality of fmi
|
|
//
|
|
int
|
|
FontMatchInfoObject::isEqual(FontMatchInfoObject *fob)
|
|
{
|
|
// Two fmi's are equal if their string representations ARE THE SAME
|
|
return (!strcmp(describe(), fob->describe()));
|
|
}
|
|
|
|
|
|
int FontMatchInfoObject::
|
|
reconstruct(const char *reconstructString)
|
|
{
|
|
// Release any stringRepresentation
|
|
releaseStringRepresentation();
|
|
|
|
// Remove all existing attributes
|
|
removeAll();
|
|
|
|
// Reconstruct the FMI from the string.
|
|
int i = 0;
|
|
int len = strlen(reconstructString);
|
|
char *fontpart = new char[len+1];
|
|
if (!fontpart)
|
|
{
|
|
// ERROR: No Memory.
|
|
return (-1);
|
|
}
|
|
const char *attr = NULL;
|
|
const char *value = NULL;
|
|
while (reconstructString && *reconstructString)
|
|
{
|
|
if (i < MAX_STANDARD_ATTRIBUTES)
|
|
{
|
|
reconstructString = scanFontpart(reconstructString, fontpart, attr, value);
|
|
if (fmi_attributes_type[i] == FMI_TYPE_CSTRING)
|
|
{
|
|
addAttribute(fmi_attributes[i], fontpart);
|
|
}
|
|
else
|
|
{
|
|
jint ival = atoi(fontpart);
|
|
addAttribute(fmi_attributes[i], ival);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
reconstructString = scanFontpart(reconstructString, fontpart, attr, value);
|
|
addAttribute(attr, (char *)value);
|
|
}
|
|
i++;
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
const char * FontMatchInfoObject::
|
|
describe(void)
|
|
{
|
|
if (stringRepresentation != NULL)
|
|
{
|
|
return (stringRepresentation);
|
|
}
|
|
|
|
wfListElement *tmp = head;
|
|
stringLen = 0;
|
|
stringMaxLen = 0;
|
|
|
|
for (; tmp; tmp = tmp->next)
|
|
{
|
|
struct fmi_attr_store *ele = (struct fmi_attr_store *)tmp->item;
|
|
addToString(stringRepresentation, stringLen, stringMaxLen, ele);
|
|
}
|
|
return (stringRepresentation);
|
|
}
|
|
|
|
//
|
|
// Private method implementations
|
|
//
|
|
|
|
int FontMatchInfoObject::
|
|
addAttribute(const char *attr, const char *value)
|
|
{
|
|
struct fmi_attr_store *ele = new fmi_attr_store;
|
|
if (!ele)
|
|
{
|
|
// no memory
|
|
return (-1);
|
|
}
|
|
|
|
ele->attr = attr;
|
|
ele->valueType = FMI_TYPE_CSTRING;
|
|
ele->u.stringValue = CopyString(value);
|
|
add(ele);
|
|
|
|
// Sync stringRepresentation
|
|
addToString(stringRepresentation, stringLen, stringMaxLen, ele);
|
|
|
|
return (0);
|
|
}
|
|
|
|
|
|
int FontMatchInfoObject::
|
|
addAttribute(const char *attr, jint value)
|
|
{
|
|
struct fmi_attr_store *ele = new fmi_attr_store;
|
|
if (!ele)
|
|
{
|
|
// no memory
|
|
return (-1);
|
|
}
|
|
|
|
ele->attr = attr;
|
|
ele->valueType = FMI_TYPE_JINT;
|
|
ele->u.intValue = value;
|
|
add(ele);
|
|
|
|
// Sync stringRepresentation
|
|
addToString(stringRepresentation, stringLen, stringMaxLen, ele);
|
|
|
|
return (0);
|
|
}
|
|
|
|
void
|
|
/*ARGSUSED*/
|
|
free_fmi_attr_store(wfList *object, void *item)
|
|
{
|
|
struct fmi_attr_store *ele = (struct fmi_attr_store *)item;
|
|
if (ele)
|
|
{
|
|
if (ele->valueType == FMI_TYPE_CSTRING)
|
|
{
|
|
// Free the copy of the string we took
|
|
delete[] (char *)ele->u.stringValue;
|
|
}
|
|
delete ele;
|
|
}
|
|
}
|
|
|
|
#define MY_BLOCK_SIZE 16
|
|
static const char needsEscape[] = {
|
|
FMI_FONTPART_DEFAULT, FMI_FONTPART_SEPERATOR,
|
|
FMI_FONTPART_ESCAPE, FMI_FONTPART_ATTRSEPERATOR,
|
|
'\0',
|
|
};
|
|
|
|
|
|
int FontMatchInfoObject::
|
|
addToString(const char *&str, int &strLen, int &strMaxLen, struct fmi_attr_store *ele)
|
|
{
|
|
const char *value;
|
|
char *newValue = NULL;
|
|
char strValue[64]; // XXX There must be a better way to do this.
|
|
int ret = 0;
|
|
|
|
addToString(str, strLen, strMaxLen, FMI_FONTPART_SEPERATOR);
|
|
if (count() > MAX_STANDARD_ATTRIBUTES)
|
|
{
|
|
// Add the attribute also
|
|
addToString(str, strLen, strMaxLen, ele->attr);
|
|
addToString(str, strLen, strMaxLen, ":");
|
|
}
|
|
|
|
if (ele->valueType == FMI_TYPE_JINT)
|
|
{
|
|
strValue[0] = '\0';
|
|
if (ele->u.intValue > 0)
|
|
{
|
|
sprintf(strValue, "%d", ele->u.intValue);
|
|
}
|
|
value = strValue;
|
|
}
|
|
else
|
|
{
|
|
// Escape {:-*} in value. These have special meaning to us.
|
|
value = ele->u.stringValue;
|
|
if (value && *value)
|
|
{
|
|
newValue = EscapeString(value, needsEscape);
|
|
if (!newValue)
|
|
{
|
|
// ERROR: No memory
|
|
return (-1);
|
|
}
|
|
value = newValue;
|
|
}
|
|
}
|
|
ret = addToString(str, strLen, strMaxLen, value);
|
|
if (newValue)
|
|
{
|
|
delete[] newValue;
|
|
}
|
|
return (ret);
|
|
}
|
|
|
|
int FontMatchInfoObject::
|
|
addToString(const char *&str, int &strLen, int &strMaxLen, const char *value)
|
|
{
|
|
int valueLen = 0;
|
|
if (!value || !*value)
|
|
{
|
|
// Use default symbol
|
|
return (0);
|
|
}
|
|
valueLen = strlen(value);
|
|
|
|
while ((strMaxLen - strLen) <= valueLen)
|
|
{
|
|
str = (char *)WF_REALLOC((char*)str,strMaxLen + MY_BLOCK_SIZE);
|
|
if (str == NULL) return 0;
|
|
strMaxLen += MY_BLOCK_SIZE;
|
|
}
|
|
|
|
strcpy((char*)(str+strLen), value);
|
|
strLen += valueLen;
|
|
return strLen;
|
|
}
|
|
|
|
int FontMatchInfoObject::
|
|
addToString(const char *&str, int &strLen, int &strMaxLen, const char value)
|
|
{
|
|
if ((strMaxLen - strLen) <= 1)
|
|
{
|
|
str = (char *)WF_REALLOC((char*)str,strMaxLen + MY_BLOCK_SIZE);
|
|
if (str == NULL) return 0;
|
|
strMaxLen += MY_BLOCK_SIZE;
|
|
}
|
|
|
|
*((char *)(str+strLen)) = value;
|
|
strLen++;
|
|
*((char *)(str+strLen)) = '\0';
|
|
return strLen;
|
|
}
|
|
|
|
int FontMatchInfoObject::
|
|
releaseStringRepresentation(void)
|
|
{
|
|
if (stringRepresentation)
|
|
{
|
|
WF_FREE((char*)stringRepresentation);
|
|
stringRepresentation = NULL;
|
|
stringLen = stringMaxLen = 0;
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
//
|
|
// Scans for the next fontpart from str and copies it into fontpart.
|
|
// Assumes enough memory has been allocated for fontpart.
|
|
// If value/attr are non-null, then points value and attr to their
|
|
// appropriate places in fontpart
|
|
//
|
|
const char *FontMatchInfoObject::
|
|
scanFontpart(const char *str, char *fontpart, const char *&value, const char *&attr)
|
|
{
|
|
char *attrEnd = NULL;
|
|
|
|
if (attr) attr = NULL;
|
|
if (value) value = fontpart;
|
|
if (*str == FMI_FONTPART_SEPERATOR)
|
|
str++;
|
|
while (*str && *str != FMI_FONTPART_SEPERATOR)
|
|
{
|
|
if (*str == FMI_FONTPART_ESCAPE)
|
|
{
|
|
str++;
|
|
}
|
|
else
|
|
{
|
|
if (*str == FMI_FONTPART_ATTRSEPERATOR)
|
|
{
|
|
attrEnd = fontpart+1;
|
|
}
|
|
|
|
}
|
|
*fontpart++ = *str++;
|
|
}
|
|
*fontpart = '\0';
|
|
|
|
if (attrEnd)
|
|
{
|
|
if (attr) attr = fontpart;
|
|
*attrEnd = '\0';
|
|
if (value) value = attrEnd+1;
|
|
}
|
|
return (str);
|
|
}
|