This commit is contained in:
vladimir%pobox.com 2005-08-20 05:36:47 +00:00
Родитель 85e103d8ae
Коммит 8603ea4fbf
67 изменённых файлов: 9118 добавлений и 85 удалений

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

@ -89,7 +89,7 @@ DIRS += xprintutil xprint
endif
ifdef MOZ_ENABLE_CAIRO_GFX
DIRS += cairo
DIRS += thebes
else
ifdef MOZ_ENABLE_GTK
DIRS += gtk

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

154
gfx/src/thebes/Makefile.in Normal file
Просмотреть файл

@ -0,0 +1,154 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla 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/MPL/
#
# 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 thebes gfx
#
# The Initial Developer of the Original Code is
# mozilla.org.
# Portions created by the Initial Developer are Copyright (C) 2005
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Vladimir Vukicevic <vladimir@pobox.com>
#
# 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 MPL, 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 MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = gfx
LIBRARY_NAME = gkgfxthebes
EXPORT_LIBRARY = 1
IS_COMPONENT = 1
MODULE_NAME = nsGfxModule
GRE_MODULE = 1
LIBXUL_LIBRARY = 1
REQUIRES = xpcom \
string \
cairo \
libpixman \
glitz \
thebes \
gfx \
widget \
intl \
view \
pref \
uconv \
unicharutil \
locale \
necko \
content \
layout \
dom \
debug \
imglib2 \
$(ZLIB_REQUIRES) \
$(NULL)
CPPSRCS = \
nsThebesDeviceContext.cpp \
nsThebesDrawingSurface.cpp \
nsThebesImage.cpp \
nsThebesRegion.cpp \
nsThebesBlender.cpp \
nsThebesGfxFactory.cpp \
nsThebesRenderingContext.cpp \
nsThebesScreen.cpp \
nsThebesScreenManager.cpp \
$(NULL)
SHARED_LIBRARY_LIBS = \
$(DIST)/lib/$(LIB_PREFIX)mozutil_s.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)gfxshared_s.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)mozcairo.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)mozlibpixman.$(LIB_SUFFIX) \
$(DIST)/lib/$(LIB_PREFIX)thebes.$(LIB_SUFFIX) \
$(NULL)
ifdef MOZ_ENABLE_GLITZ
SHARED_LIBRARY_LIBS += $(DIST)/lib/$(LIB_PREFIX)mozglitz.$(LIB_SUFFIX)
endif
EXTRA_DSO_LIBS = gkgfx
ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
CPPSRCS += nsSystemFontsGTK2.cpp
ifdef MOZ_ENABLE_PANGO
CPPSRCS += nsFontMetricsPango.cpp \
mozilla-decoder.cpp \
$(NULL)
endif
ifdef MOZ_ENABLE_GLITZ
SHARED_LIBRARY_LIBS += $(DIST)/lib/$(LIB_PREFIX)mozglitzglx.$(LIB_SUFFIX)
REQUIRES += glitzglx
endif
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
CPPSRCS += nsFontMetricsWin2.cpp \
nsSystemFontsWin.cpp \
$(NULL)
REQUIRES += glitzwgl
_OS_LIBS = usp10
OS_LIBS += $(call EXPAND_LIBNAME,$(_OS_LIBS))
endif
EXPORTS += nsIThebesRenderingContext.h
LOCAL_INCLUDES = \
-I$(srcdir)/. \
-I$(srcdir)/.. \
-I$(srcdir)/../shared \
$(NULL)
EXTRA_DSO_LDOPTS += \
$(EXTRA_DSO_LIBS) \
$(MOZ_COMPONENT_LIBS) \
$(MOZ_UNICHARUTIL_LIBS) \
$(MOZ_JS_LIBS) \
$(TK_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk
CXXFLAGS += $(TK_CFLAGS)
CFLAGS += $(TK_CFLAGS)
ifdef MOZ_ENABLE_GTK2
DEFINES += -DMOZ_ENABLE_GTK2
endif

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

@ -0,0 +1,375 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Christopher Blizzard
* <blizzard@mozilla.org>. Portions created by the Initial Developer
* are Copyright (C) 2004 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#define PANGO_ENABLE_BACKEND
#define PANGO_ENABLE_ENGINE
#include "mozilla-decoder.h"
#include <pango/pangoxft.h>
#include <pango/pangofc-fontmap.h>
#include <pango/pangofc-font.h>
#include <gdk/gdkx.h>
#include "nsString.h"
#include "nsIPersistentProperties2.h"
#include "nsNetUtil.h"
#include "nsReadableUtils.h"
#include "nsICharsetConverterManager.h"
#include "nsICharRepresentable.h"
#include "nsCompressedCharMap.h"
#undef DEBUG_CUSTOM_ENCODER
G_DEFINE_TYPE (MozillaDecoder, mozilla_decoder, PANGO_TYPE_FC_DECODER)
MozillaDecoder *mozilla_decoder_new (void);
static FcCharSet *mozilla_decoder_get_charset (PangoFcDecoder *decoder,
PangoFcFont *fcfont);
static PangoGlyph mozilla_decoder_get_glyph (PangoFcDecoder *decoder,
PangoFcFont *fcfont,
guint32 wc);
static PangoFcDecoder *mozilla_find_decoder (FcPattern *pattern,
gpointer user_data);
typedef struct _MozillaDecoderPrivate MozillaDecoderPrivate;
#define MOZILLA_DECODER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), MOZILLA_TYPE_DECODER, MozillaDecoderPrivate))
struct _MozillaDecoderPrivate {
char *family;
char *encoder;
char *cmap;
gboolean is_wide;
FcCharSet *charset;
nsCOMPtr<nsIUnicodeEncoder> uEncoder;
};
static nsICharsetConverterManager *gCharsetManager = NULL;
static NS_DEFINE_CID(kCharsetConverterManagerCID,
NS_ICHARSETCONVERTERMANAGER_CID);
// Hash tables that hold the custom encodings and custom cmaps used in
// various fonts.
GHashTable *encoder_hash = NULL;
GHashTable *cmap_hash = NULL;
GHashTable *wide_hash = NULL;
void
mozilla_decoder_init (MozillaDecoder *decoder)
{
}
void
mozilla_decoder_class_init (MozillaDecoderClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
PangoFcDecoderClass *parent_class = PANGO_FC_DECODER_CLASS (klass);
/* object_class->finalize = test_finalize; */
parent_class->get_charset = mozilla_decoder_get_charset;
parent_class->get_glyph = mozilla_decoder_get_glyph;
g_type_class_add_private (object_class, sizeof (MozillaDecoderPrivate));
}
MozillaDecoder *
mozilla_decoder_new(void)
{
return (MozillaDecoder *)g_object_new(MOZILLA_TYPE_DECODER, NULL);
}
#ifdef DEBUG_CUSTOM_ENCODER
void
dump_hash(char *key, char *val, void *arg)
{
printf("%s -> %s\n", key, val);
}
#endif
/**
* mozilla_decoders_init:
*
* #mozilla_decoders_init:
*
* This initializes all of the application-specific custom decoders
* that Mozilla uses. This should only be called once during the
* lifetime of the application.
*
* Return value: zero on success, not zero on failure.
*
**/
int
mozilla_decoders_init(void)
{
static PRBool initialized = PR_FALSE;
if (initialized)
return 0;
encoder_hash = g_hash_table_new(g_str_hash, g_str_equal);
cmap_hash = g_hash_table_new(g_str_hash, g_str_equal);
wide_hash = g_hash_table_new(g_str_hash, g_str_equal);
PRBool dumb = PR_FALSE;
nsCOMPtr<nsIPersistentProperties> props;
nsCOMPtr<nsISimpleEnumerator> encodeEnum;
NS_LoadPersistentPropertiesFromURISpec(getter_AddRefs(props),
NS_LITERAL_CSTRING("resource://gre/res/fonts/pangoFontEncoding.properties"));
if (!props)
goto loser;
// Enumerate the properties in this file and figure out all of the
// fonts for which we have custom encodings.
props->Enumerate(getter_AddRefs(encodeEnum));
if (!encodeEnum)
goto loser;
while (encodeEnum->HasMoreElements(&dumb), dumb) {
nsCOMPtr<nsIPropertyElement> prop;
encodeEnum->GetNext(getter_AddRefs(prop));
if (!prop)
goto loser;
nsCAutoString name;
prop->GetKey(name);
nsAutoString value;
prop->GetValue(value);
if (!StringBeginsWith(name, NS_LITERAL_CSTRING("encoding."))) {
printf("string doesn't begin with encoding?\n");
continue;
}
name = Substring(name, 9);
if (StringEndsWith(name, NS_LITERAL_CSTRING(".ttf"))) {
name = Substring(name, 0, name.Length() - 4);
// Strip off a .wide if it's there.
if (StringEndsWith(value, NS_LITERAL_STRING(".wide"))) {
g_hash_table_insert(wide_hash, g_strdup(name.get()),
g_strdup("wide"));
value = Substring(value, 0, name.Length() - 5);
}
g_hash_table_insert(encoder_hash,
g_strdup(name.get()),
g_strdup(NS_ConvertUTF16toUTF8(value).get()));
}
else if (StringEndsWith(name, NS_LITERAL_CSTRING(".ftcmap"))) {
name = Substring(name, 0, name.Length() - 7);
g_hash_table_insert(cmap_hash,
g_strdup(name.get()),
g_strdup(NS_ConvertUTF16toUTF8(value).get()));
}
else {
printf("unknown suffix used for mapping\n");
}
}
pango_fc_font_map_add_decoder_find_func(PANGO_FC_FONT_MAP(pango_xft_get_font_map(GDK_DISPLAY(),gdk_x11_get_default_screen())),
mozilla_find_decoder,
NULL,
NULL);
initialized = PR_TRUE;
#ifdef DEBUG_CUSTOM_ENCODER
printf("*** encoders\n");
g_hash_table_foreach(encoder_hash, (GHFunc)dump_hash, NULL);
printf("*** cmaps\n");
g_hash_table_foreach(cmap_hash, (GHFunc)dump_hash, NULL);
#endif
return 0;
loser:
return -1;
}
FcCharSet *
mozilla_decoder_get_charset (PangoFcDecoder *decoder,
PangoFcFont *fcfont)
{
MozillaDecoderPrivate *priv = MOZILLA_DECODER_GET_PRIVATE(decoder);
if (priv->charset)
return priv->charset;
// First time this has been accessed. Populate the charset.
priv->charset = FcCharSetCreate();
if (!gCharsetManager) {
CallGetService(kCharsetConverterManagerCID, &gCharsetManager);
}
nsCOMPtr<nsIUnicodeEncoder> encoder;
nsCOMPtr<nsICharRepresentable> represent;
if (!gCharsetManager)
goto end;
gCharsetManager->GetUnicodeEncoderRaw(priv->encoder, getter_AddRefs(encoder));
if (!encoder)
goto end;
encoder->SetOutputErrorBehavior(encoder->kOnError_Replace, nsnull, '?');
priv->uEncoder = encoder;
represent = do_QueryInterface(encoder);
if (!represent)
goto end;
PRUint32 map[UCS2_MAP_LEN];
memset(map, 0, sizeof(map));
represent->FillInfo(map);
for (int i = 0; i < NUM_UNICODE_CHARS; i++) {
if (IS_REPRESENTABLE(map, i))
FcCharSetAddChar(priv->charset, i);
}
end:
return priv->charset;
}
PangoGlyph
mozilla_decoder_get_glyph (PangoFcDecoder *decoder,
PangoFcFont *fcfont,
guint32 wc)
{
MozillaDecoderPrivate *priv = MOZILLA_DECODER_GET_PRIVATE(decoder);
PangoGlyph retval = 0;
PRUnichar inchar = wc;
PRInt32 inlen = 1;
char outchar[2] = {0,0};
PRInt32 outlen = 2;
priv->uEncoder->Convert(&inchar, &inlen, outchar, &outlen);
if (outlen != 1) {
printf("Warning: mozilla_decoder_get_glyph doesn't support more than one character conversions.\n");
return 0;
}
FT_Face face = pango_fc_font_lock_face(fcfont);
#ifdef DEBUG_CUSTOM_ENCODER
char *filename;
FcPatternGetString(fcfont->font_pattern, FC_FILE, 0, (FcChar8 **)&filename);
printf("filename is %s\n", filename);
#endif
// Make sure to set the right charmap before trying to get the
// glyph
if (priv->cmap) {
if (!strcmp(priv->cmap, "mac_roman")) {
FT_Select_Charmap(face, ft_encoding_apple_roman);
}
else if (!strcmp(priv->cmap, "unicode")) {
FT_Select_Charmap(face, ft_encoding_unicode);
}
else {
printf("Warning: Invalid charmap entry for family %s\n",
priv->family);
}
}
// Standard 8 bit to glyph translation
if (!priv->is_wide) {
FcChar32 blah = PRUint8(outchar[0]);
retval = FT_Get_Char_Index(face, blah);
#ifdef DEBUG_CUSTOM_ENCODER
printf("wc 0x%x outchar[0] 0x%x index 0x%x retval 0x%x face %p\n",
wc, outchar[0], blah, retval, (void *)face);
#endif
}
else {
printf("Warning: We don't support .wide fonts!\n");
retval = 0;
}
pango_fc_font_unlock_face(fcfont);
return retval;
}
PangoFcDecoder *
mozilla_find_decoder (FcPattern *pattern, gpointer user_data)
{
// Compare the family name of the font that's been opened to see
// if we have a custom decoder.
const char *orig = NULL;
FcPatternGetString(pattern, FC_FAMILY, 0, (FcChar8 **)&orig);
nsCAutoString family;
family.Assign(orig);
family.StripWhitespace();
ToLowerCase(family);
char *encoder = (char *)g_hash_table_lookup(encoder_hash, family.get());
if (!encoder)
return NULL;
MozillaDecoder *decoder = mozilla_decoder_new();
MozillaDecoderPrivate *priv = MOZILLA_DECODER_GET_PRIVATE(decoder);
priv->family = g_strdup(family.get());
priv->encoder = g_strdup(encoder);
char *cmap = (char *)g_hash_table_lookup(cmap_hash, family.get());
if (cmap)
priv->cmap = g_strdup(cmap);
char *wide = (char *)g_hash_table_lookup(wide_hash, family.get());
if (wide)
priv->is_wide = TRUE;
return PANGO_FC_DECODER(decoder);
}

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

@ -0,0 +1,72 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
*/
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Christopher Blizzard
* <blizzard@mozilla.org>. Portions created by the Initial Developer
* are Copyright (C) 2004 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _MOZILLA_DECODER_H
#define _MOZILLA_DECODER_H
#include <pango/pangofc-decoder.h>
G_BEGIN_DECLS
#define MOZILLA_TYPE_DECODER (mozilla_decoder_get_type())
#define MOZILLA_DECODER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOZILLA_TYPE_DECODER, MozillaDecoder))
#define MOZILLA_IS_DECODER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOZILLA_TYPE_DECODER))
typedef struct _MozillaDecoder MozillaDecoder;
typedef struct _MozillaDecoderClass MozillaDecoderClass;
#define MOZILLA_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOZILLA_TYPE_DECODER, MozillaDecoderClass))
#define MOZILLA_IS_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOZILLA_TYPE_DECODER))
#define MOZILLA_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOZILLA_TYPE_DECODER, MozillaDecoderClass))
struct _MozillaDecoder
{
PangoFcDecoder parent_instance;
};
struct _MozillaDecoderClass
{
PangoFcDecoderClass parent_class;
};
GType mozilla_decoder_get_type (void);
int mozilla_decoders_init (void);
G_END_DECLS
#endif /*_MOZILLA_DECODER_H */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

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

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

@ -0,0 +1,829 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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
* mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@pavlov.net>
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsFontMetricsWin2.h"
#include "nsFont.h"
#include "nsString.h"
#include "nsAutoBuffer.h"
#include <stdio.h>
#include <malloc.h>
#include <Usp10.h>
#include "cairo-win32.h"
// for using the cairo apis for fonts...
#define USE_SCALED_FONTS
NS_IMPL_ISUPPORTS1(nsFontMetricsWin, nsIFontMetrics)
#include <stdlib.h>
nsFontMetricsWin::nsFontMetricsWin()
{
_putenv("XPCOM_DEBUG_BREAK=warn");
}
nsFontMetricsWin::~nsFontMetricsWin()
{
cairo_font_face_destroy(mCairoFontFace);
cairo_scaled_font_destroy(mCairoFont);
}
static PRBool
FontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData)
{
nsFontMetricsWin* metrics = (nsFontMetricsWin*) aData;
metrics->mFonts.AppendString(aFamily);
if (aGeneric) {
metrics->mGeneric.Assign(aFamily);
//ToLowerCase(metrics->mGeneric);
return PR_FALSE; // stop
}
++metrics->mGenericIndex;
return PR_TRUE; // don't stop
}
cairo_font_face_t *
nsFontMetricsWin::MakeCairoFontFace(const nsString *aFontName)
{
cairo_font_face_t *fontFace = nsnull;
LOGFONTW logFont;
memset(&logFont, 0, sizeof(LOGFONTW));
FillLogFont(&logFont, aFontName);
fontFace = cairo_win32_font_face_create_for_logfontw(&logFont);
return fontFace;
}
cairo_scaled_font_t *
nsFontMetricsWin::MakeCairoScaledFont(cairo_t *cr, cairo_font_face_t *aFontFace)
{
cairo_scaled_font_t *font = nsnull;
float app2dev = mDeviceContext->AppUnitsToDevUnits();
double size = NSToIntRound(mFont.size * app2dev);
cairo_matrix_t sizeMatrix, ctm;
if (cr)
cairo_get_matrix(cr, &ctm);
else
cairo_matrix_init_identity(&ctm);
cairo_matrix_init_scale(&sizeMatrix, size, size);
cairo_font_options_t *fontOptions = cairo_font_options_create();
font = cairo_scaled_font_create(aFontFace, &sizeMatrix, &ctm, fontOptions);
cairo_font_options_destroy(fontOptions);
return font;
}
NS_IMETHODIMP
nsFontMetricsWin::Init(const nsFont& aFont, nsIAtom* aLangGroup,
nsIDeviceContext *aContext)
{
mFont = aFont;
mLangGroup = aLangGroup;
mDeviceContext = (nsThebesDeviceContext*)aContext;
mDev2App = aContext->DevUnitsToAppUnits();
// set up the first font in the list as the default, and we'll go from there.
mFont.EnumerateFamilies(FontEnumCallback, this);
mCairoFontFace = MakeCairoFontFace(mFonts[0]);
mCairoFont = MakeCairoScaledFont(nsnull, mCairoFontFace);
HWND win = (HWND)mDeviceContext->GetWidget();
HDC dc = ::GetDC(win);
RealizeFont(dc);
::ReleaseDC(win, dc);
return NS_OK;
}
#define CLIP_TURNOFF_FONTASSOCIATION 0x40
void
nsFontMetricsWin::FillLogFont(LOGFONTW* logFont, const nsString *aFontName)
{
float app2dev = mDeviceContext->AppUnitsToDevUnits();
logFont->lfHeight = - NSToIntRound(mFont.size * app2dev);
if (logFont->lfHeight == 0) {
logFont->lfHeight = -1;
}
// Fill in logFont structure
logFont->lfWidth = 0;
logFont->lfEscapement = 0;
logFont->lfOrientation = 0;
logFont->lfUnderline =
(mFont.decorations & NS_FONT_DECORATION_UNDERLINE)
? TRUE : FALSE;
logFont->lfStrikeOut =
(mFont.decorations & NS_FONT_DECORATION_LINE_THROUGH)
? TRUE : FALSE;
logFont->lfCharSet = DEFAULT_CHARSET;
#ifndef WINCE
logFont->lfOutPrecision = OUT_TT_PRECIS;
#else
logFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
#endif
logFont->lfClipPrecision = CLIP_TURNOFF_FONTASSOCIATION;
logFont->lfQuality = DEFAULT_QUALITY;
logFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
logFont->lfWeight = mFont.weight;
logFont->lfItalic = (mFont.style & (NS_FONT_STYLE_ITALIC | NS_FONT_STYLE_OBLIQUE))
? TRUE : FALSE; // XXX need better oblique support
int len = PR_MIN(aFontName->Length(), LF_FACESIZE);
memcpy(logFont->lfFaceName, aFontName->get(), len * 2);
logFont->lfFaceName[len] = '\0';
}
NS_IMETHODIMP
nsFontMetricsWin::Destroy()
{
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetXHeight(nscoord& aResult)
{
aResult = mXHeight;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetSuperscriptOffset(nscoord& aResult)
{
aResult = mSuperscriptOffset;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetSubscriptOffset(nscoord& aResult)
{
aResult = mSubscriptOffset;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetStrikeout(nscoord& aOffset, nscoord& aSize)
{
aOffset = mStrikeoutOffset;
aSize = mStrikeoutSize;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetUnderline(nscoord& aOffset, nscoord& aSize)
{
aOffset = mUnderlineOffset;
aSize = mUnderlineSize;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetHeight(nscoord &aHeight)
{
aHeight = mMaxHeight;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetInternalLeading(nscoord &aLeading)
{
aLeading = mInternalLeading;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetExternalLeading(nscoord &aLeading)
{
aLeading = mExternalLeading;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetEmHeight(nscoord &aHeight)
{
aHeight = mEmHeight;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetEmAscent(nscoord &aAscent)
{
aAscent = mEmAscent;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetEmDescent(nscoord &aDescent)
{
aDescent = mEmDescent;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetMaxHeight(nscoord &aHeight)
{
aHeight = mMaxHeight;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetMaxAscent(nscoord &aAscent)
{
aAscent = mMaxAscent;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetMaxDescent(nscoord &aDescent)
{
aDescent = mMaxDescent;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetMaxAdvance(nscoord &aAdvance)
{
aAdvance = mMaxAdvance;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetLangGroup(nsIAtom** aLangGroup)
{
*aLangGroup = mLangGroup;
NS_IF_ADDREF(*aLangGroup);
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetFontHandle(nsFontHandle &aHandle)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsFontMetricsWin::GetAveCharWidth(nscoord& aAveCharWidth)
{
aAveCharWidth = mAveCharWidth;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetSpaceWidth(nscoord& aSpaceCharWidth)
{
aSpaceCharWidth = mSpaceWidth;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetLeading(nscoord& aLeading)
{
aLeading = mInternalLeading;
return NS_OK;
}
NS_IMETHODIMP
nsFontMetricsWin::GetNormalLineHeight(nscoord& aLineHeight)
{
aLineHeight = mEmHeight + mInternalLeading;
return NS_OK;
}
PRInt32
nsFontMetricsWin::MeasureOrDrawUniscribe(nsThebesRenderingContext *aContext,
const PRUnichar *aString, PRUint32 aLength,
PRBool aDraw, PRInt32 aX, PRInt32 aY, const PRInt32 *aSpacing)
{
HDC aDC = (HDC)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC);
float app2dev = mDeviceContext->AppUnitsToDevUnits();
int loops = 0;
cairo_t *cr = (cairo_t*)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_CAIRO_CONTEXT);
PRBool isComplex = (::ScriptIsComplex(aString, aLength, SIC_COMPLEX) == S_OK);
PRInt32 length = 0;
HRESULT rv;
int numItems, maxItems = 2;
SCRIPT_CACHE sc = NULL;
SCRIPT_CONTROL *control = nsnull;
SCRIPT_STATE *state = nsnull;
PRBool rtl = ((::GetTextAlign(aDC) & TA_RTLREADING) == TA_RTLREADING);
if (rtl) {
control = (SCRIPT_CONTROL *)malloc(sizeof(SCRIPT_CONTROL));
state = (SCRIPT_STATE *)malloc(sizeof(SCRIPT_STATE));
memset(control, 0, sizeof(control));
memset(state, 0, sizeof(state));
control->fNeutralOverride = 1;
state->uBidiLevel = 1;
}
SCRIPT_ITEM *items = (SCRIPT_ITEM *)malloc(maxItems*sizeof(SCRIPT_ITEM));
while ((rv = ScriptItemize(aString, aLength, maxItems, control, state,
items, &numItems)) == E_OUTOFMEMORY) {
maxItems *= 2;
items = (SCRIPT_ITEM *)realloc(items, maxItems*sizeof(SCRIPT_ITEM));
}
for (int h=0; h<numItems; h++) {
int i = (rtl) ? numItems - h - 1 : h;
const PRUnichar *itemChars = aString + items[i].iCharPos;
PRUint32 itemLength = items[i+1].iCharPos - items[i].iCharPos;
int numGlyphs = 0, maxGlyphs = 1.5 * itemLength + 16;
WORD *glyphs = (WORD *)malloc(maxGlyphs*sizeof(WORD));
WORD *clusters = (WORD *)malloc(itemLength*sizeof(WORD));
SCRIPT_VISATTR *attr = (SCRIPT_VISATTR *)malloc(maxGlyphs*sizeof(SCRIPT_VISATTR));
items[i].a.fLogicalOrder = 1;
cairo_font_face_t *fontFace = nsnull;
cairo_scaled_font_t *scaledFont = nsnull;
TRY_AGAIN:
int fontIndex = 0;
TRY_AGAIN_SAME_SCRIPT:
loops++;
SaveDC(aDC);
if (fontFace && scaledFont) {
cairo_font_face_destroy(fontFace);
cairo_scaled_font_destroy(scaledFont);
}
fontFace = MakeCairoFontFace(mFonts[fontIndex]);
scaledFont = MakeCairoScaledFont(cr, fontFace);
cairo_set_font_face(cr, fontFace);
cairo_set_font_size(cr, NSToIntRound(mFont.size * app2dev));
cairo_win32_scaled_font_select_font(scaledFont, aDC);
double cairofontfactor = cairo_win32_scaled_font_get_metrics_factor(scaledFont);
if (!isComplex)
items[i].a.eScript = SCRIPT_UNDEFINED;
while ((rv = ScriptShape(aDC, &sc, itemChars, itemLength,
maxGlyphs, &items[i].a,
glyphs, clusters,
attr, &numGlyphs)) == E_OUTOFMEMORY) {
maxGlyphs *= 2;
glyphs = (WORD *)realloc(glyphs, maxGlyphs*sizeof(WORD));
attr = (SCRIPT_VISATTR *)realloc(attr, maxGlyphs*sizeof(SCRIPT_VISATTR));
}
if (rv == USP_E_SCRIPT_NOT_IN_FONT) {
if (fontIndex < mFonts.Count() - 1) {
fontIndex++;
cairo_win32_scaled_font_done_font(scaledFont);
RestoreDC(aDC, -1);
goto TRY_AGAIN_SAME_SCRIPT;
} else {
// try again with SCRIPT_UNDEFINED
items[i].a.eScript = SCRIPT_UNDEFINED;
cairo_win32_scaled_font_done_font(scaledFont);
RestoreDC(aDC, -1);
goto TRY_AGAIN;
}
}
if (numGlyphs > 0 && glyphs[0] == 0) {
if (fontIndex < mFonts.Count() - 1) {
fontIndex++;
cairo_win32_scaled_font_done_font(scaledFont);
RestoreDC(aDC, -1);
goto TRY_AGAIN_SAME_SCRIPT;
}
// otherwise we fail to draw the characters so give up and continue on.
}
if (rv == 0) {
ABC abc;
GOFFSET *offsets = (GOFFSET *)malloc(numGlyphs*sizeof(GOFFSET));
int *advance = (int *)malloc(numGlyphs*sizeof(int));
rv = ScriptPlace(aDC, &sc, glyphs, numGlyphs, attr, &items[i].a,
advance, offsets, &abc);
if (rv != S_OK)
printf("error ScriptPlacing\n");
#ifdef DEBUG_tor
fprintf(stderr, "ABC[%d]: %d %d %d\n", i, abc.abcA, abc.abcB, abc.abcC);
#endif
if (!aDraw) {
length += NSToCoordRound((abc.abcA + abc.abcB + abc.abcC) * cairofontfactor * (mFont.size * app2dev);
} else {
PRInt32 *spacing = 0;
PRInt32 justTotal = 0;
if (aSpacing) {
/* need to correct for layout/gfx spacing mismatch */
#ifdef DEBUG_tor
fprintf(stderr, "advn: ");
for (int j=0; j<numGlyphs; j++) {
fprintf(stderr, "%4d,", advance[j]);
}
fprintf(stderr, "\n");
fprintf(stderr, "clus: ");
for (j=0; j<itemLength; j++)
fprintf(stderr, "%4d,", clusters[j]);
fprintf(stderr, "\n");
fprintf(stderr, "attr: ");
for (j=0; j<numGlyphs; j++)
fprintf(stderr, "0x%2x,", attr[j]);
fprintf(stderr, "\n");
#endif
// hacky inefficient justification: take the excess of what layout
// thinks the width is over what uniscribe thinks the width is and
// share it evenly between the justification opportunities
PRInt32 layoutTotal = 0;
for (PRUint32 j = items[i].iCharPos; j < items[i+1].iCharPos; j++) {
layoutTotal += NSToIntRound(aSpacing[j] * app2dev);
}
PRInt32 gfxTotal = abc.abcA + abc.abcB + abc.abcC;
if (layoutTotal > gfxTotal) {
spacing = (PRInt32 *)malloc(numGlyphs*sizeof(PRInt32));
justTotal = layoutTotal - gfxTotal;
#if 0
ScriptJustify(attr, advance, numGlyphs, justTotal, 1, spacing);
#else
memcpy(spacing, advance, sizeof(PRInt32)*numGlyphs);
int justOpps = 0;
int lookForOpp = 0;
for (j = 0; j < numGlyphs-1; j++) {
if (attr[j+1].uJustification > 1) {
++justOpps;
}
}
if (justOpps > 0) {
int eachJust = justTotal / justOpps;
for (j=0; j<numGlyphs-1; j++) {
if (attr[j+1].uJustification > 1) {
--justOpps;
if (justOpps == 0) {
spacing[j] += justTotal;
} else {
spacing[j] += eachJust;
justTotal -= eachJust;
}
}
}
}
#endif
#ifdef DEBUG_tor
fprintf(stderr, "hand: ");
for (j=0; j<numGlyphs; j++) {
fprintf(stderr, "%4d,", spacing[j]);
}
fprintf(stderr, "\n");
#endif
}
}
double cairoToPixels = cairofontfactor * (mFont.size * app2dev);
cairo_glyph_t *cglyphs = (cairo_glyph_t*)malloc(numGlyphs*sizeof(cairo_glyph_t));
PRInt32 offset = 0;
for (PRInt32 k = 0; k < numGlyphs; k++) {
cglyphs[k].index = glyphs[k];
cglyphs[k].x = aX + offset + NSToCoordRound(offsets[k].du * cairoToPixels);
cglyphs[k].y = aY + NSToCoordRound(offsets[k].dv * cairoToPixels);
offset += NSToCoordRound(advance[k] * cairoToPixels);
#if 0
if (aSpacing)
offset += NSToIntRound(aSpacing[k] * app2dev) * cairoToPixels;
#endif
}
cairo_show_glyphs(cr, cglyphs, numGlyphs);
free(cglyphs);
aX += NSToCoordRound((abs(abc.abcA) + abc.abcB + abs(abc.abcC) + justTotal) * cairoToPixels);
free(spacing);
}
free(offsets);
free(advance);
cairo_font_face_destroy(fontFace);
cairo_scaled_font_destroy(scaledFont);
cairo_win32_scaled_font_done_font(scaledFont);
RestoreDC(aDC, -1);
}
free(glyphs);
free(clusters);
free(attr);
}
free(items);
// printf("loops: %d\n", loops - numItems);
return length;
}
nsresult
nsFontMetricsWin::GetWidth(const char* aString, PRUint32 aLength, nscoord& aWidth,
nsThebesRenderingContext *aContext)
{
PRInt32 aFontID = 0;
return GetWidth(PromiseFlatString(NS_ConvertUTF8toUTF16(aString, aLength)).get(),
aLength, aWidth, &aFontID, aContext);
}
nsresult
nsFontMetricsWin::GetWidth(const PRUnichar* aString, PRUint32 aLength,
nscoord& aWidth, PRInt32 *aFontID,
nsThebesRenderingContext *aContext)
{
// if (::ScriptIsComplex(aString, aLength, SIC_COMPLEX) == S_OK) {
aWidth = MeasureOrDrawUniscribe(aContext, aString, aLength, PR_FALSE, 0, 0, NULL);
float f;
f = mDeviceContext->DevUnitsToAppUnits();
aWidth = NSToCoordRound(aWidth * f);
#if 0
} else {
::GetTextExtentPoint32W(aDC, aString, aLength, &size);
size.cx -= mOverhangCorrection;
return size.cx;
}
#endif
return NS_OK;
}
// Get the text dimensions for this string
nsresult
nsFontMetricsWin::GetTextDimensions(const PRUnichar* aString,
PRUint32 aLength,
nsTextDimensions& aDimensions,
PRInt32* aFontID)
{
return NS_OK;
}
nsresult
nsFontMetricsWin::GetTextDimensions(const char* aString,
PRInt32 aLength,
PRInt32 aAvailWidth,
PRInt32* aBreaks,
PRInt32 aNumBreaks,
nsTextDimensions& aDimensions,
PRInt32& aNumCharsFit,
nsTextDimensions& aLastWordDimensions,
PRInt32* aFontID)
{
return NS_OK;
}
nsresult
nsFontMetricsWin::GetTextDimensions(const PRUnichar* aString,
PRInt32 aLength,
PRInt32 aAvailWidth,
PRInt32* aBreaks,
PRInt32 aNumBreaks,
nsTextDimensions& aDimensions,
PRInt32& aNumCharsFit,
nsTextDimensions& aLastWordDimensions,
PRInt32* aFontID)
{
return NS_OK;
}
// Draw a string using this font handle on the surface passed in.
nsresult
nsFontMetricsWin::DrawString(const char *aString, PRUint32 aLength,
nscoord aX, nscoord aY,
const nscoord* aSpacing,
nsThebesRenderingContext *aContext)
{
return DrawString(PromiseFlatString(NS_ConvertUTF8toUTF16(aString, aLength)).get(),
aLength, aX, aY, 0, aSpacing, aContext);
}
// aCachedOffset will be updated with a new offset.
nsresult
nsFontMetricsWin::DrawString(const PRUnichar* aString, PRUint32 aLength,
nscoord aX, nscoord aY,
PRInt32 aFontID,
const nscoord* aSpacing,
nsThebesRenderingContext *aContext)
{
float app2dev = mDeviceContext->AppUnitsToDevUnits();
MeasureOrDrawUniscribe(aContext, aString, aLength, PR_TRUE,
NSToIntRound(aX * app2dev), NSToIntRound(aY * app2dev), aSpacing);
return NS_OK;
}
#ifdef MOZ_MATHML
// These two functions get the bounding metrics for this handle,
// updating the aBoundingMetrics in Points. This means that the
// caller will have to update them to twips before passing it
// back.
nsresult
nsFontMetricsWin::GetBoundingMetrics(const char *aString, PRUint32 aLength,
nsBoundingMetrics &aBoundingMetrics)
{
return NS_OK;
}
// aCachedOffset will be updated with a new offset.
nsresult
nsFontMetricsWin::GetBoundingMetrics(const PRUnichar *aString,
PRUint32 aLength,
nsBoundingMetrics &aBoundingMetrics,
PRInt32 *aFontID)
{
return NS_OK;
}
#endif /* MOZ_MATHML */
// Set the direction of the text rendering
nsresult
nsFontMetricsWin::SetRightToLeftText(PRBool aIsRTL)
{
return NS_OK;
}
void
nsFontMetricsWin::RealizeFont(HDC dc)
{
float app2dev = mDeviceContext->AppUnitsToDevUnits();
SaveDC(dc);
cairo_win32_scaled_font_select_font(mCairoFont, dc);
double cairofontfactor = cairo_win32_scaled_font_get_metrics_factor(mCairoFont);
double multiplier = mDev2App * cairofontfactor * NSToIntRound(mFont.size * app2dev);
// Get font metrics
OUTLINETEXTMETRIC oMetrics;
TEXTMETRIC& metrics = oMetrics.otmTextMetrics;
nscoord onePixel = NSToCoordRound(1 * mDev2App);
nscoord descentPos = 0;
if (0 < ::GetOutlineTextMetrics(dc, sizeof(oMetrics), &oMetrics)) {
// mXHeight = NSToCoordRound(oMetrics.otmsXHeight * mDev2App); XXX not really supported on windows
mXHeight = NSToCoordRound((float)metrics.tmAscent * multiplier * 0.56f); // 50% of ascent, best guess for true type
mSuperscriptOffset = NSToCoordRound(oMetrics.otmptSuperscriptOffset.y * multiplier);
mSubscriptOffset = NSToCoordRound(oMetrics.otmptSubscriptOffset.y * multiplier);
mStrikeoutSize = PR_MAX(onePixel, NSToCoordRound(oMetrics.otmsStrikeoutSize * multiplier));
mStrikeoutOffset = NSToCoordRound(oMetrics.otmsStrikeoutPosition * multiplier);
mUnderlineSize = PR_MAX(onePixel, NSToCoordRound(oMetrics.otmsUnderscoreSize * multiplier));
mUnderlineOffset = NSToCoordRound(oMetrics.otmsUnderscorePosition * multiplier);
// Begin -- section of code to get the real x-height with GetGlyphOutline()
GLYPHMETRICS gm;
MAT2 mMat = { 1, 0, 0, 1 }; // glyph transform matrix (always identity in our context)
DWORD len = GetGlyphOutlineW(dc, PRUnichar('x'), GGO_METRICS, &gm, 0, nsnull, &mMat);
if (GDI_ERROR != len && gm.gmptGlyphOrigin.y > 0) {
mXHeight = NSToCoordRound(gm.gmptGlyphOrigin.y * multiplier);
}
// End -- getting x-height
}
else {
// Make a best-effort guess at extended metrics
// this is based on general typographic guidelines
::GetTextMetrics(dc, &metrics);
mXHeight = NSToCoordRound((float)metrics.tmAscent * mDev2App * 0.56f); // 56% of ascent, best guess for non-true type
mSuperscriptOffset = mXHeight; // XXX temporary code!
mSubscriptOffset = mXHeight; // XXX temporary code!
mStrikeoutSize = onePixel; // XXX this is a guess
mStrikeoutOffset = NSToCoordRound(mXHeight / 2.0f); // 50% of xHeight
mUnderlineSize = onePixel; // XXX this is a guess
mUnderlineOffset = -NSToCoordRound((float)metrics.tmDescent * mDev2App * 0.30f); // 30% of descent
}
mInternalLeading = NSToCoordRound(metrics.tmInternalLeading * multiplier);
mExternalLeading = NSToCoordRound(metrics.tmExternalLeading * multiplier);
mEmHeight = NSToCoordRound((metrics.tmHeight - metrics.tmInternalLeading) *
multiplier);
mEmAscent = NSToCoordRound((metrics.tmAscent - metrics.tmInternalLeading) *
multiplier);
mEmDescent = NSToCoordRound(metrics.tmDescent * multiplier);
mMaxHeight = NSToCoordRound(metrics.tmHeight * multiplier);
mMaxAscent = NSToCoordRound(metrics.tmAscent * multiplier);
mMaxDescent = NSToCoordRound(metrics.tmDescent * multiplier);
mMaxAdvance = NSToCoordRound(metrics.tmMaxCharWidth * multiplier);
mAveCharWidth = PR_MAX(1, NSToCoordRound(metrics.tmAveCharWidth * multiplier));
#if 0
// descent position is preferred, but we need to make sure there is enough
// space available. Baseline need to be raised so that underline will stay
// within boundary.
// only do this for CJK to minimize possible risk
if (IsCJKLangGroupAtom(mLangGroup.get())) {
if (gDoingLineheightFixup &&
mInternalLeading+mExternalLeading > mUnderlineSize &&
descentPos < mUnderlineOffset) {
mEmAscent -= mUnderlineSize;
mEmDescent += mUnderlineSize;
mMaxAscent -= mUnderlineSize;
mMaxDescent += mUnderlineSize;
mUnderlineOffset = descentPos;
}
}
#endif
// Cache the width of a single space.
SIZE size;
::GetTextExtentPoint32(dc, " ", 1, &size);
//size.cx -= font->mOverhangCorrection;
mSpaceWidth = NSToCoordRound(size.cx * multiplier);
cairo_win32_scaled_font_done_font(mCairoFont);
RestoreDC(dc, -1);
}

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

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

@ -0,0 +1,113 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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
* Christopher Blizzard <blizzard@mozilla.org>.
* Portions created by the Initial Developer are Copyright (C) 2002
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __nsIThebesFontMetrics_h
#define __nsIThebesFontMetrics_h
#include "nsIFontMetrics.h"
#include "nsIRenderingContext.h"
class nsThebesRenderingContext;
class nsIThebesFontMetrics : public nsIFontMetrics {
public:
// Get the width for this string. aWidth will be updated with the
// width in points, not twips. Callers must convert it if they
// want it in another format.
virtual nsresult GetWidth(const char* aString, PRUint32 aLength,
nscoord& aWidth, nsThebesRenderingContext *aContext) = 0;
// aCachedOffset will be updated with a new offset.
virtual nsresult GetWidth(const PRUnichar* aString, PRUint32 aLength,
nscoord& aWidth, PRInt32 *aFontID,
nsThebesRenderingContext *aContext) = 0;
// Get the text dimensions for this string
virtual nsresult GetTextDimensions(const PRUnichar* aString,
PRUint32 aLength,
nsTextDimensions& aDimensions,
PRInt32* aFontID) = 0;
virtual nsresult GetTextDimensions(const char* aString,
PRInt32 aLength,
PRInt32 aAvailWidth,
PRInt32* aBreaks,
PRInt32 aNumBreaks,
nsTextDimensions& aDimensions,
PRInt32& aNumCharsFit,
nsTextDimensions& aLastWordDimensions,
PRInt32* aFontID) = 0;
virtual nsresult GetTextDimensions(const PRUnichar* aString,
PRInt32 aLength,
PRInt32 aAvailWidth,
PRInt32* aBreaks,
PRInt32 aNumBreaks,
nsTextDimensions& aDimensions,
PRInt32& aNumCharsFit,
nsTextDimensions& aLastWordDimensions,
PRInt32* aFontID) = 0;
// Draw a string using this font handle on the surface passed in.
virtual nsresult DrawString(const char *aString, PRUint32 aLength,
nscoord aX, nscoord aY,
const nscoord* aSpacing,
nsThebesRenderingContext *aContext) = 0;
// aCachedOffset will be updated with a new offset.
virtual nsresult DrawString(const PRUnichar* aString, PRUint32 aLength,
nscoord aX, nscoord aY,
PRInt32 aFontID,
const nscoord* aSpacing,
nsThebesRenderingContext *aContext) = 0;
#ifdef MOZ_MATHML
// These two functions get the bounding metrics for this handle,
// updating the aBoundingMetrics in Points. This means that the
// caller will have to update them to twips before passing it
// back.
virtual nsresult GetBoundingMetrics(const char *aString, PRUint32 aLength,
nsBoundingMetrics &aBoundingMetrics) = 0;
// aCachedOffset will be updated with a new offset.
virtual nsresult GetBoundingMetrics(const PRUnichar *aString,
PRUint32 aLength,
nsBoundingMetrics &aBoundingMetrics,
PRInt32 *aFontID) = 0;
#endif /* MOZ_MATHML */
// Set the direction of the text rendering
virtual nsresult SetRightToLeftText(PRBool aIsRTL) = 0;
};
#endif /* __nsIThebesFontMetrics_h */

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

@ -0,0 +1,57 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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
* Christopher Blizzard <blizzard@mozilla.org>.
* Portions created by the Initial Developer are Copyright (C) 2002
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __nsIThebesRenderingContext_h
#define __nsIThebesRenderingContext_h
#include "nsIRenderingContext.h"
// IID for the nsIRenderingContext interface
#define NSI_THEBES_RENDERING_CONTEXT_IID \
{ 0x8591c4c6, 0x41d4, 0x485a, \
{ 0xb2, 0x4f, 0x9d, 0xe1, 0x9b, 0x69, 0xce, 0x02 } }
class nsIThebesRenderingContext : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NSI_THEBES_RENDERING_CONTEXT_IID)
NS_IMETHOD CreateDrawingSurface(nsNativeWidget aWidget, nsIDrawingSurface* &aSurface) = 0;
};
#endif /* __nsIThebesRenderingContext_h */

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

@ -0,0 +1,340 @@
// for strtod()
#include <stdlib.h>
#include "nsIRenderingContext.h"
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <pango/pango.h>
#include <pango/pangox.h>
#include <pango/pango-fontmap.h>
#include "nsSystemFontsGTK2.h"
static PRInt32 GetXftDPI(void);
static void AppendFontFFREName(nsString& aString, const char* aXLFDName);
#define DEFAULT_TWIP_FONT_SIZE 240
nsSystemFontsGTK2::nsSystemFontsGTK2(float aPixelsToTwips)
: mDefaultFont("sans-serif", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
NS_FONT_WEIGHT_NORMAL, NS_FONT_DECORATION_NONE,
DEFAULT_TWIP_FONT_SIZE),
mButtonFont("sans-serif", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
NS_FONT_WEIGHT_NORMAL, NS_FONT_DECORATION_NONE,
DEFAULT_TWIP_FONT_SIZE),
mFieldFont("sans-serif", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
NS_FONT_WEIGHT_NORMAL, NS_FONT_DECORATION_NONE,
DEFAULT_TWIP_FONT_SIZE),
mMenuFont("sans-serif", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
NS_FONT_WEIGHT_NORMAL, NS_FONT_DECORATION_NONE,
DEFAULT_TWIP_FONT_SIZE)
{
/*
* Much of the widget creation code here is similar to the code in
* nsLookAndFeel::InitColors().
*/
// mDefaultFont
GtkWidget *label = gtk_label_new("M");
GtkWidget *parent = gtk_fixed_new();
GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP);
gtk_container_add(GTK_CONTAINER(parent), label);
gtk_container_add(GTK_CONTAINER(window), parent);
gtk_widget_ensure_style(label);
GetSystemFontInfo(label, &mDefaultFont, aPixelsToTwips);
gtk_widget_destroy(window); // no unref, windows are different
// mFieldFont
GtkWidget *entry = gtk_entry_new();
parent = gtk_fixed_new();
window = gtk_window_new(GTK_WINDOW_POPUP);
gtk_container_add(GTK_CONTAINER(parent), entry);
gtk_container_add(GTK_CONTAINER(window), parent);
gtk_widget_ensure_style(entry);
GetSystemFontInfo(entry, &mFieldFont, aPixelsToTwips);
gtk_widget_destroy(window); // no unref, windows are different
// mMenuFont
GtkWidget *accel_label = gtk_accel_label_new("M");
GtkWidget *menuitem = gtk_menu_item_new();
GtkWidget *menu = gtk_menu_new();
gtk_object_ref(GTK_OBJECT(menu));
gtk_object_sink(GTK_OBJECT(menu));
gtk_container_add(GTK_CONTAINER(menuitem), accel_label);
gtk_menu_append(GTK_MENU(menu), menuitem);
gtk_widget_ensure_style(accel_label);
GetSystemFontInfo(accel_label, &mMenuFont, aPixelsToTwips);
gtk_widget_unref(menu);
// mButtonFont
parent = gtk_fixed_new();
GtkWidget *button = gtk_button_new();
label = gtk_label_new("M");
window = gtk_window_new(GTK_WINDOW_POPUP);
gtk_container_add(GTK_CONTAINER(button), label);
gtk_container_add(GTK_CONTAINER(parent), button);
gtk_container_add(GTK_CONTAINER(window), parent);
gtk_widget_ensure_style(label);
GetSystemFontInfo(label, &mButtonFont, aPixelsToTwips);
gtk_widget_destroy(window); // no unref, windows are different
}
#ifdef MOZ_ENABLE_COREXFONTS
static void xlfd_from_pango_font_description(GtkWidget *aWidget,
const PangoFontDescription *aFontDesc,
nsString& aFontName);
#endif /* MOZ_ENABLE_COREXFONTS */
nsresult
nsSystemFontsGTK2::GetSystemFontInfo(GtkWidget *aWidget, nsFont* aFont,
float aPixelsToTwips) const
{
GtkSettings *settings = gtk_widget_get_settings(aWidget);
aFont->style = NS_FONT_STYLE_NORMAL;
aFont->decorations = NS_FONT_DECORATION_NONE;
gchar *fontname;
g_object_get(settings, "gtk-font-name", &fontname, NULL);
PangoFontDescription *desc;
desc = pango_font_description_from_string(fontname);
aFont->systemFont = PR_TRUE;
g_free(fontname);
aFont->name.Truncate();
#ifdef MOZ_ENABLE_XFT
aFont->name.Assign(PRUnichar('"'));
aFont->name.AppendWithConversion(pango_font_description_get_family(desc));
aFont->name.Append(PRUnichar('"'));
#endif /* MOZ_ENABLE_XFT */
#ifdef MOZ_ENABLE_COREXFONTS
// if name already set by Xft, do nothing
if (!aFont->name.Length()) {
xlfd_from_pango_font_description(aWidget, desc, aFont->name);
}
#endif /* MOZ_ENABLE_COREXFONTS */
aFont->weight = pango_font_description_get_weight(desc);
float size = float(pango_font_description_get_size(desc) / PANGO_SCALE);
#ifdef MOZ_ENABLE_XFT
PRInt32 dpi = GetXftDPI();
if (dpi != 0) {
// pixels/inch * twips/pixel * inches/twip == 1, except it isn't, since
// our idea of dpi may be different from Xft's.
size *= float(dpi) * aPixelsToTwips * (1.0f/1440.0f);
}
#endif /* MOZ_ENABLE_XFT */
aFont->size = NSFloatPointsToTwips(size);
pango_font_description_free(desc);
return NS_OK;
}
#if defined(MOZ_ENABLE_COREXFONTS)
// xlfd_from_pango_font_description copied from vte, which was
// written by nalin@redhat.com, and added some codes.
static void
xlfd_from_pango_font_description(GtkWidget *aWidget,
const PangoFontDescription *aFontDesc,
nsString& aFontName)
{
char *spec;
PangoContext *context;
PangoFont *font;
PangoXSubfont *subfont_ids;
PangoFontMap *fontmap;
int *subfont_charsets, i, count = 0;
char *subfont;
char *encodings[] = {
"ascii-0",
"big5-0",
"dos-437",
"dos-737",
"gb18030.2000-0",
"gb18030.2000-1",
"gb2312.1980-0",
"iso8859-1",
"iso8859-2",
"iso8859-3",
"iso8859-4",
"iso8859-5",
"iso8859-7",
"iso8859-8",
"iso8859-9",
"iso8859-10",
"iso8859-15",
"iso10646-0",
"iso10646-1",
"jisx0201.1976-0",
"jisx0208.1983-0",
"jisx0208.1990-0",
"jisx0208.1997-0",
"jisx0212.1990-0",
"jisx0213.2000-1",
"jisx0213.2000-2",
"koi8-r",
"koi8-u",
"koi8-ub",
"ksc5601.1987-0",
"ksc5601.1992-3",
"tis620-0",
"iso8859-13",
"microsoft-cp1251"
"misc-fontspecific",
};
#if XlibSpecificationRelease >= 6
XOM xom;
#endif
if (!aFontDesc) {
return;
}
context = gtk_widget_get_pango_context(GTK_WIDGET(aWidget));
pango_context_set_language (context, gtk_get_default_language ());
fontmap = pango_x_font_map_for_display(GDK_DISPLAY());
if (!fontmap) {
return;
}
font = pango_font_map_load_font(fontmap, context, aFontDesc);
if (!font) {
return;
}
#if XlibSpecificationRelease >= 6
xom = XOpenOM (GDK_DISPLAY(), NULL, NULL, NULL);
if (xom) {
XOMCharSetList cslist;
int n_encodings = 0;
cslist.charset_count = 0;
XGetOMValues (xom,
XNRequiredCharSet, &cslist,
NULL);
n_encodings = cslist.charset_count;
if (n_encodings) {
char **xom_encodings = (char**) g_malloc (sizeof(char*) * n_encodings);
for (i = 0; i < n_encodings; i++) {
xom_encodings[i] = g_ascii_strdown (cslist.charset_list[i], -1);
}
count = pango_x_list_subfonts(font, xom_encodings, n_encodings,
&subfont_ids, &subfont_charsets);
for(i = 0; i < n_encodings; i++) {
g_free (xom_encodings[i]);
}
g_free (xom_encodings);
}
XCloseOM (xom);
}
#endif
if (count == 0) {
count = pango_x_list_subfonts(font, encodings, G_N_ELEMENTS(encodings),
&subfont_ids, &subfont_charsets);
}
for (i = 0; i < count; i++) {
subfont = pango_x_font_subfont_xlfd(font, subfont_ids[i]);
AppendFontFFREName(aFontName, subfont);
g_free(subfont);
aFontName.Append(PRUnichar(','));
}
spec = pango_font_description_to_string(aFontDesc);
if (subfont_ids != NULL) {
g_free(subfont_ids);
}
if (subfont_charsets != NULL) {
g_free(subfont_charsets);
}
g_free(spec);
}
#endif /* MOZ_ENABLE_COREXFONTS */
#if defined(MOZ_ENABLE_COREXFONTS) || defined(MOZ_WIDGET_GTK)
#define LOCATE_MINUS(pos, str) { \
pos = str.FindChar('-'); \
if (pos < 0) \
return ; \
}
#define NEXT_MINUS(pos, str) { \
pos = str.FindChar('-', pos+1); \
if (pos < 0) \
return ; \
}
static void
AppendFontFFREName(nsString& aString, const char* aXLFDName)
{
// convert fontname from XFLD to FFRE and append, ie. from
// -adobe-courier-medium-o-normal--14-140-75-75-m-90-iso8859-15
// to
// adobe-courier-iso8859-15
nsCAutoString nameStr(aXLFDName);
PRInt32 pos1, pos2;
// remove first '-' and everything before it.
LOCATE_MINUS(pos1, nameStr);
nameStr.Cut(0, pos1+1);
// skip foundry and family name
LOCATE_MINUS(pos1, nameStr);
NEXT_MINUS(pos1, nameStr);
pos2 = pos1;
// find '-' just before charset registry
for (PRInt32 i=0; i < 10; i++) {
NEXT_MINUS(pos2, nameStr);
}
// remove everything in between
nameStr.Cut(pos1, pos2-pos1);
aString.AppendWithConversion(nameStr.get());
}
#endif /* MOZ_ENABLE_COREXFONTS || MOZ_WIDGET_GTK*/
#ifdef MOZ_ENABLE_XFT
/* static */
PRInt32
GetXftDPI(void)
{
char *val = XGetDefault(GDK_DISPLAY(), "Xft", "dpi");
if (val) {
char *e;
double d = strtod(val, &e);
if (e != val)
return NSToCoordRound(d);
}
return 0;
}
#endif /* MOZ_ENABLE_XFT */

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

@ -0,0 +1,43 @@
#ifndef _NS_SYSTEMFONTSGTK2_H_
#define _NS_SYSTEMFONTSGTK2_H_
#include <nsFont.h>
class nsSystemFontsGTK2
{
public:
nsSystemFontsGTK2(float aPixelsToTwips);
const nsFont& GetDefaultFont() { return mDefaultFont; }
const nsFont& GetMenuFont() { return mMenuFont; }
const nsFont& GetFieldFont() { return mFieldFont; }
const nsFont& GetButtonFont() { return mButtonFont; }
private:
nsresult GetSystemFontInfo(GtkWidget *aWidget, nsFont* aFont,
float aPixelsToTwips) const;
/*
* The following system font constants exist:
*
* css2: http://www.w3.org/TR/REC-CSS2/fonts.html#x27
* eSystemFont_Caption, eSystemFont_Icon, eSystemFont_Menu,
* eSystemFont_MessageBox, eSystemFont_SmallCaption,
* eSystemFont_StatusBar,
* // css3
* eSystemFont_Window, eSystemFont_Document,
* eSystemFont_Workspace, eSystemFont_Desktop,
* eSystemFont_Info, eSystemFont_Dialog,
* eSystemFont_Button, eSystemFont_PullDownMenu,
* eSystemFont_List, eSystemFont_Field,
* // moz
* eSystemFont_Tooltips, eSystemFont_Widget
*/
nsFont mDefaultFont;
nsFont mButtonFont;
nsFont mFieldFont;
nsFont mMenuFont;
};
#endif /* _NS_SYSTEMFONTSGTK2_H_ */

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

@ -0,0 +1,20 @@
#ifndef _NS_SYSTEMFONTSWIN_H_
#define _NS_SYSTEMFONTSWIN_H_
#include <nsFont.h>
#include <nsIDeviceContext.h>
class nsSystemFontsWin
{
public:
nsSystemFontsWin(float aPixelsToTwips);
nsresult CopyLogFontToNSFont(HDC* aHDC, const LOGFONT* ptrLogFont,
nsFont* aFont, PRBool aIsWide = PR_FALSE) const;
nsresult GetSysFontInfo(HDC aHDC, nsSystemFontID anID, nsFont* aFont) const;
nsresult GetSystemFont(nsSystemFontID anID, nsFont *aFont) const;
};
#endif /* _NS_SYSTEMFONTSWIN_H_ */

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

@ -0,0 +1,92 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 thebes gfx
*
* The Initial Developer of the Original Code is
* mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsMemory.h"
#include "nsThebesBlender.h"
#include "nsThebesDrawingSurface.h"
NS_IMPL_ISUPPORTS1(nsThebesBlender, nsIBlender)
nsThebesBlender::nsThebesBlender()
: mThebesDC(nsnull)
{
}
nsThebesBlender::~nsThebesBlender()
{
}
NS_IMETHODIMP
nsThebesBlender::Init(nsIDeviceContext *aContext)
{
mThebesDC = NS_STATIC_CAST(nsThebesDeviceContext*, aContext);
return NS_OK;
}
NS_IMETHODIMP
nsThebesBlender::Blend(PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth, PRInt32 aHeight,
nsIDrawingSurface* aSrc, nsIDrawingSurface* aDest,
PRInt32 aDX, PRInt32 aDY,
float aSrcOpacity,
nsIDrawingSurface* aSecondSrc,
nscolor aSrcBackColor, nscolor aSecondSrcBackColor)
{
NS_WARNING("Should be using Push/PopFilter instead");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsThebesBlender::Blend(PRInt32 aSX, PRInt32 aSY, PRInt32 aWidth, PRInt32 aHeight,
nsIRenderingContext *aSrc, nsIRenderingContext *aDest,
PRInt32 aDX, PRInt32 aDY, float aSrcOpacity,
nsIRenderingContext *aSecondSrc, nscolor aSrcBackColor,
nscolor aSecondSrcBackColor)
{
NS_WARNING("Should be using Push/PopFilter instead");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsThebesBlender::GetAlphas(const nsRect& aRect, nsIDrawingSurface* aBlack,
nsIDrawingSurface* aWhite, PRUint8** aAlphas)
{
NS_WARNING("This needs to be implemented somehow");
return NS_ERROR_NOT_IMPLEMENTED;
}

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

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

@ -0,0 +1,537 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 thebes gfx
*
* The Initial Developer of the Original Code is
* mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
* Stuart Parmenter <pavlov@pavlov.net>
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIServiceManager.h"
#include "nsThebesDeviceContext.h"
#include "nsThebesRenderingContext.h"
#include "nsThebesDrawingSurface.h"
#include "nsIView.h"
#ifdef MOZ_ENABLE_GTK2
// for getenv
#include <stdlib.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include "nsFontMetricsUtils.h"
#include "nsFont.h"
#include <pango/pango.h>
#include <pango/pangox.h>
#include <pango/pango-fontmap.h>
#ifdef MOZ_ENABLE_GLITZ
#include "glitz-glx.h"
#endif /* GLITZ */
#endif /* GTK2 */
#ifdef MOZ_ENABLE_GTK2
#include "nsSystemFontsGTK2.h"
static nsSystemFontsGTK2 *gSystemFonts = nsnull;
#elif XP_WIN
#include <cairo-win32.h>
#include "nsSystemFontsWin.h"
static nsSystemFontsWin *gSystemFonts = nsnull;
#include <Usp10.h>
#else
#error Need to declare gSystemFonts!
#endif
#ifdef MOZ_ENABLE_GTK2
extern "C" {
static int x11_error_handler (Display *dpy, XErrorEvent *err) {
NS_ASSERTION(PR_FALSE, "X Error");
return 0;
}
}
#endif
#ifdef PR_LOGGING
PRLogModuleInfo* gThebesGFXLog = nsnull;
#endif
NS_IMPL_ISUPPORTS_INHERITED0(nsThebesDeviceContext, DeviceContextImpl)
nsThebesDeviceContext::nsThebesDeviceContext()
{
#ifdef PR_LOGGING
if (!gThebesGFXLog)
gThebesGFXLog = PR_NewLogModule("thebesGfx");
#endif
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("#### Creating DeviceContext %p\n", this));
mDevUnitsToAppUnits = 1.0f;
mAppUnitsToDevUnits = 1.0f;
mCPixelScale = 1.0f;
mZoom = 1.0f;
mTextZoom = 1.0f;
mWidgetSurfaceCache.Init();
#ifdef XP_WIN
SCRIPT_DIGITSUBSTITUTE sds;
ScriptRecordDigitSubstitution(LOCALE_USER_DEFAULT, &sds);
#endif
}
nsThebesDeviceContext::~nsThebesDeviceContext()
{
}
NS_IMETHODIMP
nsThebesDeviceContext::Init(nsNativeWidget aWidget)
{
#ifdef XP_WIN
// XXX we should really look at the widget for printing and such, but this widget is currently always null...
HDC dc = GetDC(nsnull);
mPixelsToTwips = (float)NSIntPointsToTwips(72) / (float)GetDeviceCaps(dc, LOGPIXELSY);
if (GetDeviceCaps(dc, TECHNOLOGY) == DT_RASDISPLAY)
mPixelsToTwips = (float)NSToIntRound(mPixelsToTwips);
mTwipsToPixels = 1.0f / mPixelsToTwips;
ReleaseDC(nsnull, dc);
#else
mTwipsToPixels = 96 / (float) NSIntPointsToTwips(72);
mPixelsToTwips = 1.0f / mTwipsToPixels;
#endif
mWidget = aWidget;
if (!mScreenManager)
mScreenManager = do_GetService("@mozilla.org/gfx/screenmanager;1");
if (!mScreenManager)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIScreen> screen;
mScreenManager->GetPrimaryScreen (getter_AddRefs(screen));
if (screen) {
PRInt32 x, y, width, height;
screen->GetRect (&x, &y, &width, &height);
mWidthFloat = float(width);
mHeightFloat = float(height);
}
#ifdef MOZ_ENABLE_GTK2
if (getenv ("MOZ_X_SYNC")) {
PR_LOG (gThebesGFXLog, PR_LOG_DEBUG, ("+++ Enabling XSynchronize\n"));
XSynchronize (gdk_x11_get_default_xdisplay(), True);
XSetErrorHandler(x11_error_handler);
}
#endif
mWidth = -1;
mHeight = -1;
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::CreateRenderingContext(nsIView *aView,
nsIRenderingContext *&aContext)
{
NS_ENSURE_ARG_POINTER(aView);
NS_PRECONDITION(aView->HasWidget(), "View has no widget!");
nsCOMPtr<nsIWidget> widget;
widget = aView->GetWidget();
return CreateRenderingContext(widget, aContext);
}
NS_IMETHODIMP
nsThebesDeviceContext::CreateRenderingContext(nsIDrawingSurface *aSurface,
nsIRenderingContext *&aContext)
{
nsresult rv;
aContext = nsnull;
nsCOMPtr<nsIRenderingContext> pContext;
rv = CreateRenderingContextInstance(*getter_AddRefs(pContext));
if (NS_SUCCEEDED(rv)) {
rv = pContext->Init(this, aSurface);
if (NS_SUCCEEDED(rv)) {
aContext = pContext;
NS_ADDREF(aContext);
}
}
return rv;
}
NS_IMETHODIMP
nsThebesDeviceContext::CreateRenderingContext(nsIWidget *aWidget,
nsIRenderingContext *&aContext)
{
nsresult rv;
aContext = nsnull;
nsCOMPtr<nsIRenderingContext> pContext;
rv = CreateRenderingContextInstance(*getter_AddRefs(pContext));
if (NS_SUCCEEDED(rv)) {
rv = pContext->Init(this, aWidget);
if (NS_SUCCEEDED(rv)) {
aContext = pContext;
NS_ADDREF(aContext);
}
}
return rv;
}
NS_IMETHODIMP
nsThebesDeviceContext::CreateRenderingContext(nsIRenderingContext *&aContext)
{
NS_ERROR("CreateRenderingContext with other rendering context arg; fix this if this needs to be called");
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::CreateRenderingContextInstance(nsIRenderingContext *&aContext)
{
nsCOMPtr<nsIRenderingContext> renderingContext = new nsThebesRenderingContext();
if (!renderingContext)
return NS_ERROR_OUT_OF_MEMORY;
aContext = renderingContext;
NS_ADDREF(aContext);
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::SupportsNativeWidgets(PRBool &aSupportsWidgets)
{
aSupportsWidgets = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::GetScrollBarDimensions(float &aWidth, float &aHeight) const
{
aWidth = 10.0f * mPixelsToTwips;
aHeight = 10.0f * mPixelsToTwips;
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::GetSystemFont(nsSystemFontID aID, nsFont *aFont) const
{
nsresult status = NS_OK;
if (!gSystemFonts) {
#ifdef MOZ_ENABLE_GTK2
gSystemFonts = new nsSystemFontsGTK2(mPixelsToTwips);
#elif XP_WIN
gSystemFonts = new nsSystemFontsWin(mPixelsToTwips);
#else
#error Need to know how to create gSystemFonts, fix me!
#endif
}
#ifdef XP_WIN
gSystemFonts->GetSystemFont(aID, aFont);
return NS_OK;
#else
switch (aID) {
case eSystemFont_Menu: // css2
case eSystemFont_PullDownMenu: // css3
*aFont = gSystemFonts->GetMenuFont();
break;
case eSystemFont_Field: // css3
case eSystemFont_List: // css3
*aFont = gSystemFonts->GetFieldFont();
break;
case eSystemFont_Button: // css3
*aFont = gSystemFonts->GetButtonFont();
break;
case eSystemFont_Caption: // css2
case eSystemFont_Icon: // css2
case eSystemFont_MessageBox: // css2
case eSystemFont_SmallCaption: // css2
case eSystemFont_StatusBar: // css2
case eSystemFont_Window: // css3
case eSystemFont_Document: // css3
case eSystemFont_Workspace: // css3
case eSystemFont_Desktop: // css3
case eSystemFont_Info: // css3
case eSystemFont_Dialog: // css3
case eSystemFont_Tooltips: // moz
case eSystemFont_Widget: // moz
*aFont = gSystemFonts->GetDefaultFont();
break;
}
#endif
return status;
}
NS_IMETHODIMP
nsThebesDeviceContext::CheckFontExistence(const nsString& aFaceName)
{
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::GetDepth(PRUint32& aDepth)
{
aDepth = 24;
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::GetPaletteInfo(nsPaletteInfo& aPaletteInfo)
{
aPaletteInfo.isPaletteDevice = PR_FALSE;
aPaletteInfo.sizePalette = 0;
aPaletteInfo.numReserved = 0;
aPaletteInfo.palette = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::ConvertPixel(nscolor aColor, PRUint32 & aPixel)
{
aPixel = aColor;
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::GetDeviceSurfaceDimensions(PRInt32 &aWidth, PRInt32 &aHeight)
{
if (mWidth == -1)
mWidth = NSToIntRound(mWidthFloat * mDevUnitsToAppUnits);
if (mHeight == -1)
mHeight = NSToIntRound(mHeightFloat * mDevUnitsToAppUnits);
aWidth = mWidth;
aHeight = mHeight;
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::GetRect(nsRect &aRect)
{
if (mWidget) {
PRInt32 x,y;
PRUint32 width, height;
#if defined (MOZ_ENABLE_GTK2)
Window root_ignore;
PRUint32 bwidth_ignore, depth;
XGetGeometry(GDK_WINDOW_XDISPLAY(GDK_DRAWABLE(mWidget)),
GDK_WINDOW_XWINDOW(GDK_DRAWABLE(mWidget)),
&root_ignore, &x, &y,
&width, &height,
&bwidth_ignore, &depth);
#elif defined (XP_WIN)
// XXX
x = y = 0;
width = height = 200;
#else
#error write me
#endif
nsCOMPtr<nsIScreen> screen;
mScreenManager->ScreenForRect(x, y, width, height, getter_AddRefs(screen));
screen->GetRect(&aRect.x, &aRect.y, &aRect.width, &aRect.height);
aRect.x = NSToIntRound(mDevUnitsToAppUnits * aRect.x);
aRect.y = NSToIntRound(mDevUnitsToAppUnits * aRect.y);
aRect.width = NSToIntRound(mDevUnitsToAppUnits * aRect.width);
aRect.height = NSToIntRound(mDevUnitsToAppUnits * aRect.height);
} else {
aRect.x = 0;
aRect.y = 0;
this->GetDeviceSurfaceDimensions(aRect.width, aRect.height);
}
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::GetClientRect(nsRect &aRect)
{
nsresult rv = this->GetRect(aRect);
return rv;
}
#if defined(MOZ_ENABLE_GLITZ)
void*
nsThebesDeviceContext::GetGlitzDrawableFormat()
{
glitz_drawable_format_t* format = nsnull;
#ifdef MOZ_ENABLE_GTK2
glitz_drawable_format_t templ;
memset(&templ, 0, sizeof(templ));
templ.samples = 1; // change this to change FSAA?
templ.types.window = 1;
int defaultScreen = gdk_x11_get_default_screen();
unsigned long mask = GLITZ_FORMAT_SAMPLES_MASK | GLITZ_FORMAT_WINDOW_MASK;
format = glitz_glx_find_drawable_format (GDK_DISPLAY(), defaultScreen, mask, &templ, 0);
#endif
return format;
}
#endif
#if defined(MOZ_ENABLE_GLITZ) && defined(MOZ_ENABLE_GTK2)
void*
nsThebesDeviceContext::GetDesiredVisual()
{
Display* dpy = GDK_DISPLAY();
int defaultScreen = gdk_x11_get_default_screen();
glitz_drawable_format_t* format = (glitz_drawable_format_t*) GetGlitzDrawableFormat();
if (format) {
XVisualInfo* vinfo = glitz_glx_get_visual_info_from_format(dpy, defaultScreen, format);
GdkScreen* screen = gdk_display_get_screen(gdk_x11_lookup_xdisplay(dpy), defaultScreen);
GdkVisual* vis = gdk_x11_screen_lookup_visual(screen, vinfo->visualid);
return vis;
} else {
// GL/GLX not available, force glitz off
nsThebesDrawingSurface::mGlitzMode = 0;
}
return nsnull;
}
#endif
NS_IMETHODIMP
nsThebesDeviceContext::PrepareNativeWidget(nsIWidget* aWidget, void** aOut)
{
#if defined(MOZ_ENABLE_GLITZ) && defined(MOZ_ENABLE_GTK2)
*aOut = GetDesiredVisual();
#else
*aOut = nsnull;
#endif
return NS_OK;
}
/*
* below methods are for printing and are not implemented
*/
NS_IMETHODIMP
nsThebesDeviceContext::GetDeviceContextFor(nsIDeviceContextSpec *aDevice,
nsIDeviceContext *&aContext)
{
/* we don't do printing */
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsThebesDeviceContext::PrepareDocument(PRUnichar * aTitle,
PRUnichar* aPrintToFileName)
{
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::BeginDocument(PRUnichar* aTitle,
PRUnichar* aPrintToFileName,
PRInt32 aStartPage,
PRInt32 aEndPage)
{
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::EndDocument(void)
{
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::AbortDocument(void)
{
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::BeginPage(void)
{
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::EndPage(void)
{
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::SetAltDevice(nsIDeviceContext* aAltDC)
{
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::GetAltDevice(nsIDeviceContext** aAltDC)
{
*aAltDC = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsThebesDeviceContext::SetUseAltDC(PRUint8 aValue, PRBool aOn)
{
return NS_OK;
}
/** End printing methods **/

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

@ -0,0 +1,140 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 thebes gfx
*
* The Initial Developer of the Original Code is
* mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
* Stuart Parmenter <pavlov@pavlov.net>
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _NS_THEBESDEVICECONTEXT_H_
#define _NS_THEBESDEVICECONTEXT_H_
#include "nsIScreenManager.h"
#include "nsDeviceContext.h"
#include "nsRefPtrHashtable.h"
#include "nsHashKeys.h"
#include "prlog.h"
#include <gfxContext.h>
#ifdef PR_LOGGING
extern PRLogModuleInfo* gThebesGFXLog;
#endif
class nsThebesDeviceContext : public DeviceContextImpl
{
public:
nsThebesDeviceContext();
virtual ~nsThebesDeviceContext();
NS_DECL_ISUPPORTS_INHERITED
NS_IMETHOD Init(nsNativeWidget aWidget);
NS_IMETHOD CreateRenderingContext(nsIView *aView, nsIRenderingContext *&aContext);
NS_IMETHOD CreateRenderingContext(nsIDrawingSurface *aSurface, nsIRenderingContext *&aContext);
NS_IMETHOD CreateRenderingContext(nsIWidget *aWidget, nsIRenderingContext *&aContext);
NS_IMETHOD CreateRenderingContext(nsIRenderingContext *&aContext);
NS_IMETHOD CreateRenderingContextInstance(nsIRenderingContext *&aContext);
NS_IMETHOD SupportsNativeWidgets(PRBool &aSupportsWidgets);
NS_IMETHOD PrepareNativeWidget(nsIWidget* aWidget, void** aOut);
NS_IMETHOD GetScrollBarDimensions(float &aWidth, float &aHeight) const;
NS_IMETHOD GetSystemFont(nsSystemFontID aID, nsFont *aFont) const;
NS_IMETHOD CheckFontExistence(const nsString& aFaceName);
NS_IMETHOD GetDepth(PRUint32& aDepth);
NS_IMETHOD GetPaletteInfo(nsPaletteInfo& aPaletteInfo);
NS_IMETHOD ConvertPixel(nscolor aColor, PRUint32 & aPixel);
NS_IMETHOD GetDeviceSurfaceDimensions(PRInt32 &aWidth, PRInt32 &aHeight);
NS_IMETHOD GetRect(nsRect &aRect);
NS_IMETHOD GetClientRect(nsRect &aRect);
#ifdef MOZ_ENABLE_GLITZ
/* glitz_drawable_format_t */ void* GetGlitzDrawableFormat();
#ifdef MOZ_ENABLE_GTK2
/* GdkVisual */ void* GetDesiredVisual();
#endif
#endif
/* printing goop */
NS_IMETHOD GetDeviceContextFor(nsIDeviceContextSpec *aDevice,
nsIDeviceContext *&aContext);
NS_IMETHOD PrepareDocument(PRUnichar * aTitle,
PRUnichar* aPrintToFileName);
NS_IMETHOD BeginDocument(PRUnichar* aTitle,
PRUnichar* aPrintToFileName,
PRInt32 aStartPage,
PRInt32 aEndPage);
NS_IMETHOD EndDocument(void);
NS_IMETHOD AbortDocument(void);
NS_IMETHOD BeginPage(void);
NS_IMETHOD EndPage(void);
NS_IMETHOD SetAltDevice(nsIDeviceContext* aAltDC);
NS_IMETHOD GetAltDevice(nsIDeviceContext** aAltDC);
NS_IMETHOD SetUseAltDC(PRUint8 aValue, PRBool aOn);
/* end printing goop */
static void DebugShowCairoSurface (const char *aName, cairo_surface_t *aSurface);
nsNativeWidget GetWidget() { return mWidget; }
private:
nsNativeWidget mWidget;
nsCOMPtr<nsIScreenManager> mScreenManager;
float mWidthFloat;
float mHeightFloat;
PRInt32 mWidth;
PRInt32 mHeight;
nsRefPtrHashtable<nsISupportsHashKey, gfxASurface> mWidgetSurfaceCache;
};
#endif /* _NS_CAIRODEVICECONTEXT_H_ */

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

@ -0,0 +1,393 @@
/* -*- Mode: C++; tab-width: 50; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 thebes gfx
*
* The Initial Developer of the Original Code is
* mozilla.org
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
*
* 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 "nsThebesDrawingSurface.h"
#include "nsThebesDeviceContext.h"
#include "nsMemory.h"
#include "gfxImageSurface.h"
#ifdef MOZ_ENABLE_GTK2
#include <gdk/gdkx.h>
#include "gfxXlibSurface.h"
# ifdef MOZ_ENABLE_GLITZ
# include "gfxGlitzSurface.h"
# include "glitz-glx.h"
# endif
#elif XP_WIN
#include "gfxWindowsSurface.h"
#endif
#include <stdlib.h>
PRInt32 nsThebesDrawingSurface::mGlitzMode = -1;
NS_IMPL_ISUPPORTS1(nsThebesDrawingSurface, nsIDrawingSurface)
nsThebesDrawingSurface::nsThebesDrawingSurface()
{
}
nsThebesDrawingSurface::~nsThebesDrawingSurface()
{
#ifdef WIN_XP
if (mWidget)
nsNativeWidget nativeWidget = mWidget->FreeNativeData(mNativeWidget, NS_NATIVE_GRAPHIC);
#endif
}
nsresult
nsThebesDrawingSurface::Init(nsThebesDeviceContext *aDC, PRUint32 aWidth, PRUint32 aHeight, PRBool aFastAccess)
{
NS_ASSERTION(mSurface == nsnull, "Surface already initialized!");
NS_ASSERTION(aWidth > 0 && aHeight > 0, "Invalid surface dimensions!");
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsThebesDrawingSurface::Init aDC %p w %d h %d fast %d\n", this, aDC, aWidth, aHeight, aFastAccess));
mWidth = aWidth;
mHeight = aHeight;
mDC = aDC;
mNativeWidget = nsnull;
#if defined(MOZ_ENABLE_GTK2)
if (aFastAccess) {
//fprintf (stderr, "## nsThebesDrawingSurface::Init gfxImageSurface %d %d\n", aWidth, aHeight);
mSurface = new gfxImageSurface(gfxImageSurface::ImageFormatARGB32, aWidth, aHeight);
} else {
if (!UseGlitz()) {
mSurface = new gfxXlibSurface(GDK_DISPLAY(), GDK_VISUAL_XVISUAL(gdk_rgb_get_visual()), aWidth, aHeight);
} else {
# if defined(MOZ_ENABLE_GLITZ)
glitz_drawable_format_t *gdformat = (glitz_drawable_format_t*) aDC->GetGlitzDrawableFormat();
glitz_drawable_t *gdraw =
glitz_glx_create_pbuffer_drawable (GDK_DISPLAY(),
DefaultScreen(GDK_DISPLAY()),
gdformat,
aWidth,
aHeight);
glitz_format_t *gformat =
glitz_find_standard_format (gdraw, GLITZ_STANDARD_ARGB32);
glitz_surface_t *gsurf =
glitz_surface_create (gdraw,
gformat,
aWidth,
aHeight,
0,
NULL);
glitz_surface_attach (gsurf, gdraw, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR, 0, 0);
//fprintf (stderr, "## nsThebesDrawingSurface::Init Glitz PBUFFER %d %d\n", aWidth, aHeight);
mSurface = new gfxGlitzSurface (gdraw, gsurf, PR_TRUE);
# endif
}
}
#elif XP_WIN
if (aFastAccess) {
mSurface = new gfxImageSurface(gfxImageSurface::ImageFormatARGB32, aWidth, aHeight);
} else {
mSurface = new gfxWindowsSurface(aWidth, aHeight);
}
#else
#error Write me!
#endif
return NS_OK;
}
nsresult
nsThebesDrawingSurface::Init (nsThebesDeviceContext *aDC, nsIWidget *aWidget)
{
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsThebesDrawingSurface::Init aDC %p aWidget %p\n", this, aDC, aWidget));
#ifdef MOZ_ENABLE_GTK2
nsNativeWidget nativeWidget = aWidget->GetNativeData(NS_NATIVE_WIDGET);
#elif XP_WIN
mWidget = aWidget; // hold a pointer to this.. not a reference.. because we have to free the dc...
nsNativeWidget nativeWidget = aWidget->GetNativeData(NS_NATIVE_GRAPHIC);
#else
#error Write me!
#endif
Init(aDC, nativeWidget);
return NS_OK;
}
nsresult
nsThebesDrawingSurface::Init (nsThebesDeviceContext *aDC, nsNativeWidget aWidget)
{
mDC = aDC;
mNativeWidget = aWidget;
mWidth = 0;
mHeight = 0;
#ifdef MOZ_ENABLE_GTK2
NS_ASSERTION (GDK_IS_WINDOW(aWidget), "unsupported native widget type!");
if (!UseGlitz()) {
mSurface = new gfxXlibSurface(GDK_WINDOW_XDISPLAY(GDK_DRAWABLE(aWidget)),
GDK_WINDOW_XWINDOW(GDK_DRAWABLE(aWidget)),
GDK_VISUAL_XVISUAL(gdk_drawable_get_visual(GDK_DRAWABLE(aWidget))));
} else {
# if defined(MOZ_ENABLE_GLITZ)
glitz_surface_t *gsurf;
glitz_drawable_t *gdraw;
glitz_drawable_format_t *gdformat = (glitz_drawable_format_t*) aDC->GetGlitzDrawableFormat();
Display* dpy = GDK_WINDOW_XDISPLAY(GDK_DRAWABLE(aWidget));
Window wnd = GDK_WINDOW_XWINDOW(GDK_DRAWABLE(aWidget));
Window root_ignore;
int x_ignore, y_ignore;
unsigned int bwidth_ignore, width, height, depth;
XGetGeometry(dpy,
wnd,
&root_ignore, &x_ignore, &y_ignore,
&width, &height,
&bwidth_ignore, &depth);
gdraw =
glitz_glx_create_drawable_for_window (dpy,
DefaultScreen(dpy),
gdformat,
wnd,
width,
height);
glitz_format_t *gformat =
glitz_find_standard_format (gdraw, GLITZ_STANDARD_ARGB32);
gsurf =
glitz_surface_create (gdraw,
gformat,
width,
height,
0,
NULL);
glitz_surface_attach (gsurf, gdraw, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR, 0, 0);
//fprintf (stderr, "## nsThebesDrawingSurface::Init Glitz DRAWABLE %p (DC: %p)\n", aWidget, aDC);
mSurface = new gfxGlitzSurface (gdraw, gsurf, PR_TRUE);
mWidth = width;
mHeight = height;
# endif
}
#elif XP_WIN
HDC nativeDC = (HDC)aWidget;
mSurface = new gfxWindowsSurface(nativeDC);
#else
#error write me
#endif
return NS_OK;
}
#ifdef MOZ_ENABLE_GTK2
static nsresult ConvertPixmapsGTK(GdkPixmap* aPmBlack, GdkPixmap* aPmWhite,
const nsIntSize& aSize, PRUint8* aData);
#endif
nsresult
nsThebesDrawingSurface::Init (nsThebesDeviceContext *aDC,
void* aNativePixmapBlack,
void* aNativePixmapWhite,
const nsIntSize& aSrcSize)
{
PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsThebesDrawingSurface::Init aDC %p nativeBlack %p nativeWhite %p size [%d,%d]\n", this, aDC, aNativePixmapBlack, aNativePixmapWhite, aSrcSize.width, aSrcSize.height));
mWidth = aSrcSize.width;
mHeight = aSrcSize.height;
#ifdef MOZ_ENABLE_GTK2
nsresult rv;
nsRefPtr<gfxImageSurface> imgSurf = new gfxImageSurface(gfxImageSurface::ImageFormatARGB32, mWidth, mHeight);
GdkPixmap* pmBlack = NS_STATIC_CAST(GdkPixmap*, aNativePixmapBlack);
GdkPixmap* pmWhite = NS_STATIC_CAST(GdkPixmap*, aNativePixmapWhite);
rv = ConvertPixmapsGTK(pmBlack, pmWhite, aSrcSize, imgSurf->Data());
if (NS_FAILED(rv))
return rv;
mSurface = imgSurf;
#elif XP_WIN
// XXX writeme
#else
#error Write me!
#endif
return NS_OK;
}
nsresult
nsThebesDrawingSurface::PushFilter(const nsIntRect& aRect, PRBool aAreaIsOpaque, float aOpacity)
{
return NS_OK;
}
void
nsThebesDrawingSurface::PopFilter()
{
}
NS_IMETHODIMP
nsThebesDrawingSurface::Lock (PRInt32 aX, PRInt32 aY, PRUint32 aWidth, PRUint32 aHeight,
void **aBits, PRInt32 *aStride, PRInt32 *aWidthBytes,
PRUint32 aFlags)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsThebesDrawingSurface::Unlock (void)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsThebesDrawingSurface::GetDimensions (PRUint32 *aWidth, PRUint32 *aHeight)
{
*aWidth = mWidth;
*aHeight = mHeight;
return NS_OK;
}
NS_IMETHODIMP
nsThebesDrawingSurface::IsOffscreen(PRBool *aOffScreen)
{
/* remove this method */
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsThebesDrawingSurface::IsPixelAddressable(PRBool *aAddressable)
{
/* remove this method */
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsThebesDrawingSurface::GetPixelFormat(nsPixelFormat *aFormat)
{
/* remove this method, and make canvas and DumpToPPM stop using it */
return NS_ERROR_NOT_IMPLEMENTED;
}
/***** Platform specific helpers ****/
/**
* Builds an ARGB word from channel values. r,g,b must already
* be premultipled/rendered onto black.
*/
static PRInt32 BuildARGB(PRUint8 aR, PRUint8 aG, PRUint8 aB, PRUint8 aA)
{
return (aA << 24) | (aR << 16) | (aG << 8) | aB;
}
#ifdef MOZ_ENABLE_GTK2
static nsresult ConvertPixmapsGTK(GdkPixmap* aPmBlack, GdkPixmap* aPmWhite,
const nsIntSize& aSize, PRUint8* aData)
{
GdkImage *imgBlack = gdk_image_get(aPmBlack, 0, 0,
aSize.width,
aSize.height);
GdkImage *imgWhite = gdk_image_get(aPmWhite, 0, 0,
aSize.width,
aSize.height);
if (!imgBlack || !imgWhite)
return NS_ERROR_OUT_OF_MEMORY;
PRUint8* blackData = (PRUint8*)GDK_IMAGE_XIMAGE(imgBlack)->data;
PRUint8* whiteData = (PRUint8*)GDK_IMAGE_XIMAGE(imgWhite)->data;
PRInt32 bpp = GDK_IMAGE_XIMAGE(imgBlack)->bits_per_pixel;
PRInt32 stride = GDK_IMAGE_XIMAGE(imgBlack)->bytes_per_line;
PRInt32* argb = (PRInt32*)aData;
if (bpp == 24 || bpp == 32) {
PRInt32 pixSize = bpp/8;
for (PRInt32 y = 0; y < aSize.height; ++y) {
PRUint8* blackRow = blackData + y*stride;
PRUint8* whiteRow = whiteData + y*stride;
for (PRInt32 x = 0; x < aSize.width; ++x) {
PRUint8 alpha = 0;
if (blackRow[0] == whiteRow[0] &&
blackRow[1] == whiteRow[1] &&
blackRow[2] == whiteRow[2]) {
alpha = 0xFF;
}
*argb++ = BuildARGB(blackRow[2], blackRow[1],
blackRow[0], alpha);
blackRow += pixSize;
whiteRow += pixSize;
}
}
} else {
NS_ERROR("Unhandled bpp!");
}
gdk_image_unref(imgBlack);
gdk_image_unref(imgWhite);
return NS_OK;
}
#endif
PRBool
nsThebesDrawingSurface::UseGlitz()
{
#ifdef MOZ_ENABLE_GLITZ
if (mGlitzMode == -1) {
if (getenv("MOZ_GLITZ")) {
glitz_glx_init (NULL);
mGlitzMode = 1;
} else {
mGlitzMode = 0;
}
}
if (mGlitzMode)
return PR_TRUE;
#endif
return PR_FALSE;
}

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

@ -0,0 +1,109 @@
/* -*- Mode: C++; tab-width: 50; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 thebes gfx
*
* The Initial Developer of the Original Code is
* mozilla.org
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
*
* 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 ***** */
#ifndef _NSTHEBESDRAWINGSURFACE_H_
#define _NSTHEBESDRAWINGSURFACE_H_
#include "nsCOMPtr.h"
#include "nsSize.h"
#include "nsRect.h"
#include "nsIDrawingSurface.h"
#include "nsIWidget.h"
#include "gfxASurface.h"
class nsThebesDeviceContext;
class nsThebesDrawingSurface : public nsIDrawingSurface
{
public:
nsThebesDrawingSurface ();
virtual ~nsThebesDrawingSurface ();
// create a image surface if aFastAccess == TRUE, otherwise create
// a fast server pixmap
nsresult Init (nsThebesDeviceContext *aDC, PRUint32 aWidth, PRUint32 aHeight, PRBool aFastAccess);
// create a fast drawing surface for a native widget
nsresult Init (nsThebesDeviceContext *aDC, nsIWidget *aWidget);
// create a fast drawing surface for a native widget
nsresult Init (nsThebesDeviceContext *aDC, nsNativeWidget aWidget);
// create a drawing surface for a native pixmap
nsresult Init (nsThebesDeviceContext* aDC, void* aNativePixmapBlack,
void* aNativePixmapWhite,
const nsIntSize& aSize);
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIDrawingSurface interface
NS_IMETHOD Lock(PRInt32 aX, PRInt32 aY, PRUint32 aWidth, PRUint32 aHeight,
void **aBits, PRInt32 *aStride, PRInt32 *aWidthBytes,
PRUint32 aFlags);
NS_IMETHOD Unlock(void);
NS_IMETHOD GetDimensions(PRUint32 *aWidth, PRUint32 *aHeight);
NS_IMETHOD IsOffscreen(PRBool *aOffScreen);
NS_IMETHOD IsPixelAddressable(PRBool *aAddressable);
NS_IMETHOD GetPixelFormat(nsPixelFormat *aFormat);
/* utility functions */
gfxASurface *GetThebesSurface(void) { return mSurface; }
PRInt32 GetDepth() { /* XXX */ return 24; }
nsNativeWidget GetNativeWidget(void) { return mNativeWidget; }
nsresult PushFilter(const nsIntRect& aRect, PRBool aAreaIsOpaque, float aOpacity);
void PopFilter();
static PRBool UseGlitz();
static PRInt32 mGlitzMode;
private:
nsRefPtr<gfxASurface> mSurface;
nsThebesDeviceContext *mDC;
nsNativeWidget mNativeWidget;
#ifdef XP_WIN
nsIWidget *mWidget;
#endif
PRUint32 mWidth, mHeight;
};
#endif /* _NSTHEBESDRAWINGSURFACE_H_ */

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

@ -0,0 +1,383 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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
* mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@pavlov.net>
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsThebesFontMetrics.h"
#include "nsFont.h"
#include "nsDirectoryServiceDefs.h"
#include "nsIFile.h"
#include "nsString.h"
#define FONT_FILE "Vera.ttf"
#define FONT_SIZE 10
/*
#define FONT_FILE "verdana.ttf"
#define FONT_SIZE 12
*/
#define FT_FLOOR(X) ((X & -64) >> 6)
#define FT_CEIL(X) (((X + 63) & -64) >> 6)
static FT_Library ftlib = nsnull;
NS_IMPL_ISUPPORTS1(nsThebesFontMetrics, nsIFontMetrics)
nsThebesFontMetrics::nsThebesFontMetrics() :
mMaxAscent(0),
mMaxDescent(0),
mMaxAdvance(0),
mUnderlineOffset(0),
mUnderlineHeight(0)
{
NS_INIT_ISUPPORTS();
if (!ftlib) {
FT_Init_FreeType(&ftlib);
}
}
nsThebesFontMetrics::~nsThebesFontMetrics()
{
FT_Done_Face(mFace);
}
static char *
GetFontPath()
{
return strdup("/tmp/fonts/" FONT_FILE);
nsCOMPtr<nsIFile> aFile;
NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR, getter_AddRefs(aFile));
aFile->Append(NS_LITERAL_STRING(FONT_FILE));
nsAutoString pathBuf;
aFile->GetPath(pathBuf);
NS_LossyConvertUCS2toASCII pathCBuf(pathBuf);
return strdup(pathCBuf.get());
}
NS_IMETHODIMP
nsThebesFontMetrics::Init(const nsFont& aFont, nsIAtom* aLangGroup,
nsIDeviceContext *aContext)
{
mFont = aFont;
mLangGroup = aLangGroup;
mDeviceContext = aContext;
mDev2App = 1.0;
char *fontPath = GetFontPath();
FT_Error ferr = FT_New_Face(ftlib, fontPath, 0, &mFace);
if (ferr != 0) {
fprintf (stderr, "FT Error: %d\n", ferr);
return NS_ERROR_FAILURE;
}
free(fontPath);
FT_Set_Char_Size(mFace, 0, FONT_SIZE << 6, 72, 72);
mMaxAscent = mFace->bbox.yMax;
mMaxDescent = mFace->bbox.yMin;
mMaxAdvance = mFace->max_advance_width;
mUnderlineOffset = mFace->underline_position;
mUnderlineHeight = mFace->underline_thickness;
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::Destroy()
{
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetXHeight(nscoord& aResult)
{
aResult = NSToCoordRound(14 * mDev2App);
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetSuperscriptOffset(nscoord& aResult)
{
aResult = 0;
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetSubscriptOffset(nscoord& aResult)
{
aResult = 0;
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetStrikeout(nscoord& aOffset, nscoord& aSize)
{
aOffset = 0;
aSize = NSToCoordRound(1 * mDev2App);
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetUnderline(nscoord& aOffset, nscoord& aSize)
{
const FT_Fixed scale = mFace->size->metrics.y_scale;
aOffset = FT_FLOOR(FT_MulFix(mUnderlineOffset, scale));
aOffset = NSToCoordRound(aOffset * mDev2App);
aSize = FT_CEIL(FT_MulFix(mUnderlineHeight, scale));
if (aSize > 1)
aSize = 1;
aSize = NSToCoordRound(aSize * mDev2App);
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetHeight(nscoord &aHeight)
{
aHeight = NSToCoordRound((mFace->size->metrics.height >> 6) * mDev2App);
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetInternalLeading(nscoord &aLeading)
{
// aLeading = 0 * mDev2App;
aLeading = 0;
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetExternalLeading(nscoord &aLeading)
{
// aLeading = 0 * mDev2App;
aLeading = 0;
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetEmHeight(nscoord &aHeight)
{
/* ascent + descent */
#if FONT_SIZE == 10
const nscoord emHeight = 10;
#else
/* XXX this is for 12px verdana ... */
const nscoord emHeight = 14;
#endif
aHeight = NSToCoordRound(emHeight * mDev2App);
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetEmAscent(nscoord &aAscent)
{
/* units above the base line */
#if FONT_SIZE == 10
const nscoord emAscent = 10;
#else
/* XXX this is for 12px verdana ... */
const nscoord emAscent = 12;
#endif
aAscent = NSToCoordRound(emAscent * mDev2App);
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetEmDescent(nscoord &aDescent)
{
/* units below the base line */
#if FONT_SIZE == 10
const nscoord emDescent = 0;
#else
/* XXX this is for 12px verdana ... */
const nscoord emDescent = 2;
#endif
aDescent = NSToCoordRound(emDescent * mDev2App);
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetMaxHeight(nscoord &aHeight)
{
/* ascent + descent */
aHeight = FT_CEIL(FT_MulFix(mMaxAscent, mFace->size->metrics.y_scale))
- FT_CEIL(FT_MulFix(mMaxDescent, mFace->size->metrics.y_scale))
+ 1;
aHeight = NSToCoordRound(aHeight * mDev2App);
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetMaxAscent(nscoord &aAscent)
{
/* units above the base line */
aAscent = FT_CEIL(FT_MulFix(mMaxAscent, mFace->size->metrics.y_scale));
aAscent = NSToCoordRound(aAscent * mDev2App);
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetMaxDescent(nscoord &aDescent)
{
/* units below the base line */
aDescent = -FT_CEIL(FT_MulFix(mMaxDescent, mFace->size->metrics.y_scale));
aDescent = NSToCoordRound(aDescent * mDev2App);
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetMaxAdvance(nscoord &aAdvance)
{
aAdvance = FT_CEIL(FT_MulFix(mMaxAdvance, mFace->size->metrics.x_scale));
aAdvance = NSToCoordRound(aAdvance * mDev2App);
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetLangGroup(nsIAtom** aLangGroup)
{
*aLangGroup = mLangGroup;
NS_IF_ADDREF(*aLangGroup);
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetFontHandle(nsFontHandle &aHandle)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetAveCharWidth(nscoord& aAveCharWidth)
{
aAveCharWidth = NSToCoordRound(7 * mDev2App);
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetSpaceWidth(nscoord& aSpaceCharWidth)
{
FT_Load_Char(mFace, ' ', FT_LOAD_DEFAULT | FT_LOAD_NO_AUTOHINT);
aSpaceCharWidth = NSToCoordRound((mFace->glyph->advance.x >> 6) * mDev2App);
return NS_OK;
}
nscoord
nsThebesFontMetrics::MeasureString(const char *aString, PRUint32 aLength)
{
nscoord width = 0;
PRUint32 i;
int error;
FT_UInt glyph_index;
FT_UInt previous = 0;
for (i=0; i < aLength; ++i) {
glyph_index = FT_Get_Char_Index(mFace, aString[i]);
/*
if (previous && glyph_index) {
FT_Vector delta;
FT_Get_Kerning(mFace, previous, glyph_index,
FT_KERNING_DEFAULT, &delta);
width += delta.x >> 6;
}
*/
error = FT_Load_Glyph(mFace, glyph_index, FT_LOAD_DEFAULT | FT_LOAD_NO_AUTOHINT);
if (error)
continue;
width += mFace->glyph->advance.x;
previous = glyph_index;
}
return NSToCoordRound((width >> 6) * mDev2App);
}
nscoord
nsThebesFontMetrics::MeasureString(const PRUnichar *aString, PRUint32 aLength)
{
nscoord width = 0;
PRUint32 i;
int error;
FT_UInt glyph_index;
FT_UInt previous = 0;
for (i=0; i < aLength; ++i) {
glyph_index = FT_Get_Char_Index(mFace, aString[i]);
/*
if (previous && glyph_index) {
FT_Vector delta;
FT_Get_Kerning(mFace, previous, glyph_index,
FT_KERNING_DEFAULT, &delta);
width += delta.x >> 6;
}
*/
error = FT_Load_Glyph(mFace, glyph_index, FT_LOAD_DEFAULT | FT_LOAD_NO_AUTOHINT);
if (error)
continue;
width += mFace->glyph->advance.x;
previous = glyph_index;
}
return NSToCoordRound((width >> 6) * mDev2App);
}
NS_IMETHODIMP
nsThebesFontMetrics::GetLeading(nscoord& aLeading)
{
aLeading = 0;
return NS_OK;
}
NS_IMETHODIMP
nsThebesFontMetrics::GetNormalLineHeight(nscoord& aLineHeight)
{
aLineHeight = 10;
return NS_OK;
}

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

@ -0,0 +1,102 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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
* mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@pavlov.net>
* Vladimir Vukicevic <vladimir@pobox.com>
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef NSTHEBESFONTMETRICS__H__
#define NSTHEBESFONTMETRICS__H__
#include "nsIFontMetrics.h"
#include "nsCOMPtr.h"
#include "nsIDeviceContext.h"
#include "nsIAtom.h"
#include <ft2build.h>
#include FT_FREETYPE_H
class nsThebesFontMetrics : public nsIFontMetrics
{
public:
nsThebesFontMetrics();
virtual ~nsThebesFontMetrics();
NS_DECL_ISUPPORTS
NS_IMETHOD Init(const nsFont& aFont, nsIAtom* aLangGroup,
nsIDeviceContext *aContext);
NS_IMETHOD Destroy();
NS_IMETHOD GetXHeight(nscoord& aResult);
NS_IMETHOD GetSuperscriptOffset(nscoord& aResult);
NS_IMETHOD GetSubscriptOffset(nscoord& aResult);
NS_IMETHOD GetStrikeout(nscoord& aOffset, nscoord& aSize);
NS_IMETHOD GetUnderline(nscoord& aOffset, nscoord& aSize);
NS_IMETHOD GetHeight(nscoord &aHeight);
NS_IMETHOD GetInternalLeading(nscoord &aLeading);
NS_IMETHOD GetExternalLeading(nscoord &aLeading);
NS_IMETHOD GetEmHeight(nscoord &aHeight);
NS_IMETHOD GetEmAscent(nscoord &aAscent);
NS_IMETHOD GetEmDescent(nscoord &aDescent);
NS_IMETHOD GetMaxHeight(nscoord &aHeight);
NS_IMETHOD GetMaxAscent(nscoord &aAscent);
NS_IMETHOD GetMaxDescent(nscoord &aDescent);
NS_IMETHOD GetMaxAdvance(nscoord &aAdvance);
NS_IMETHOD GetLangGroup(nsIAtom** aLangGroup);
NS_IMETHOD GetFontHandle(nsFontHandle &aHandle);
NS_IMETHOD GetAveCharWidth(nscoord& aAveCharWidth);
NS_IMETHOD GetSpaceWidth(nscoord& aSpaceCharWidth);
NS_IMETHOD GetLeading(nscoord& aLeading);
NS_IMETHOD GetNormalLineHeight(nscoord& aLineHeight);
/* local methods */
nscoord MeasureString(const char *aString, PRUint32 aLength);
nscoord MeasureString(const PRUnichar *aString, PRUint32 aLength);
private:
FT_Face mFace;
nsCOMPtr<nsIDeviceContext> mDeviceContext;
nsCOMPtr<nsIAtom> mLangGroup;
float mDev2App;
long mMaxAscent;
long mMaxDescent;
short mMaxAdvance;
long mUnderlineOffset;
long mUnderlineHeight;
};
#endif /* NSTHEBESFONTMETRICS__H__ */

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

@ -0,0 +1,166 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 thebes gfx
*
* The Initial Developer of the Original Code is
* mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIGenericFactory.h"
#include "nsIModule.h"
#include "nsCOMPtr.h"
#include "nsGfxCIID.h"
#include "nsScriptableRegion.h"
#include "gfxImageFrame.h"
#include "nsThebesDeviceContext.h"
#include "nsThebesRenderingContext.h"
#include "nsThebesImage.h"
#include "nsThebesRegion.h"
#include "nsThebesScreen.h"
#include "nsThebesScreenManager.h"
#include "nsThebesBlender.h"
#ifdef MOZ_ENABLE_PANGO
#include "nsFontMetricsPango.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFontMetricsPango)
#endif
#ifdef XP_WIN
#include "nsFontMetricsWin2.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFontMetricsWin)
#endif
NS_GENERIC_FACTORY_CONSTRUCTOR(nsThebesBlender)
NS_GENERIC_FACTORY_CONSTRUCTOR(gfxImageFrame)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsThebesDeviceContext)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsThebesRenderingContext)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsThebesImage)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsThebesRegion)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsThebesScreenManager)
static NS_IMETHODIMP nsScriptableRegionConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
nsresult rv;
nsIScriptableRegion *inst = nsnull;
if ( !aResult )
{
rv = NS_ERROR_NULL_POINTER;
return rv;
}
*aResult = nsnull;
if (aOuter)
{
rv = NS_ERROR_NO_AGGREGATION;
return rv;
}
nsCOMPtr <nsIRegion> rgn;
NS_NEWXPCOM(rgn, nsThebesRegion);
nsCOMPtr<nsIScriptableRegion> scriptableRgn;
if (rgn != nsnull)
{
scriptableRgn = new nsScriptableRegion(rgn);
inst = scriptableRgn;
}
if (!inst)
{
rv = NS_ERROR_OUT_OF_MEMORY;
return rv;
}
NS_ADDREF(inst);
// release our variable above now that we have created our owning
// reference - we don't want this to go out of scope early!
scriptableRgn = nsnull;
rv = inst->QueryInterface(aIID, aResult);
NS_RELEASE(inst);
return rv;
}
static const nsModuleComponentInfo components[] =
{
{ "Thebes nsFontMetrics",
NS_FONT_METRICS_CID,
"@mozilla.org/gfx/fontmetrics;1",
#ifdef MOZ_ENABLE_PANGO
nsFontMetricsPangoConstructor
#elif XP_WIN
nsFontMetricsWinConstructor
#else
#error write me!
#endif
},
{ "Thebes Device Context",
NS_DEVICE_CONTEXT_CID,
"@mozilla.org/gfx/devicecontext;1",
nsThebesDeviceContextConstructor },
{ "Thebes Rendering Context",
NS_RENDERING_CONTEXT_CID,
"@mozilla.org/gfx/renderingcontext;1",
nsThebesRenderingContextConstructor },
{ "Thebes nsImage",
NS_IMAGE_CID,
"@mozilla.org/gfx/image;1",
nsThebesImageConstructor },
{ "Thebes Region",
NS_REGION_CID,
"@mozilla.org/gfx/region/nsThebes;1",
nsThebesRegionConstructor },
{ "Thebes Screen Manager",
NS_SCREENMANAGER_CID,
"@mozilla.org/gfx/screenmanager;1",
nsThebesScreenManagerConstructor },
{ "Scriptable Region",
NS_SCRIPTABLE_REGION_CID,
"@mozilla.org/gfx/region;1",
nsScriptableRegionConstructor },
{ "Thebes Blender",
NS_BLENDER_CID,
"@mozilla.org/gfx/blender;1",
nsThebesBlenderConstructor },
{ "image frame",
GFX_IMAGEFRAME_CID,
"@mozilla.org/gfx/image/frame;2",
gfxImageFrameConstructor, }
};
PR_STATIC_CALLBACK(void)
nsThebesGfxModuleDtor(nsIModule *self)
{
}
NS_IMPL_NSGETMODULE_WITH_DTOR(nsGfxModule, components, nsThebesGfxModuleDtor)

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

@ -0,0 +1,643 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 thebes gfx
*
* The Initial Developer of the Original Code is
* mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsMemory.h"
#include "nsColor.h"
#include "nsThebesDeviceContext.h"
#include "nsThebesRenderingContext.h"
#include "nsThebesDrawingSurface.h"
#include "nsThebesImage.h"
#include "gfxContext.h"
#include "gfxPattern.h"
#ifdef MOZ_ENABLE_GTK2
#include <gdk/gdkx.h>
#include "gfxXlibSurface.h"
#ifdef MOZ_ENABLE_GLITZ
#include "glitz-glx.h"
#include "gfxGlitzSurface.h"
#endif
#endif
static PRUint8 Unpremultiply(PRUint8 aVal, PRUint8 aAlpha);
static void ARGBToThreeChannel(PRUint32* aARGB, PRUint8* aData);
static PRUint8 Premultiply(PRUint8 aVal, PRUint8 aAlpha);
static PRUint32 ThreeChannelToARGB(PRUint8* aData, PRUint8 aAlpha);
NS_IMPL_ISUPPORTS1(nsThebesImage, nsIImage)
nsThebesImage::nsThebesImage()
: mWidth(0),
mHeight(0),
mDecoded(0,0,0,0),
mLockedData(nsnull),
mLockedAlpha(nsnull),
mAlphaDepth(0),
mLocked(PR_FALSE),
mHadAnyData(PR_FALSE),
mUpToDate(PR_FALSE)
{
}
nsresult
nsThebesImage::Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequirements aMaskRequirements)
{
NS_ASSERTION(aDepth == 24, "nsThebesImage::Init called with depth != 24");
gfxImageSurface::gfxImageFormat format;
mWidth = aWidth;
mHeight = aHeight;
switch(aMaskRequirements)
{
case nsMaskRequirements_kNeeds1Bit:
mAlphaDepth = 1;
format = gfxImageSurface::ImageFormatARGB32;
break;
case nsMaskRequirements_kNeeds8Bit:
mAlphaDepth = 8;
format = gfxImageSurface::ImageFormatARGB32;
break;
default:
mAlphaDepth = 0;
format = gfxImageSurface::ImageFormatARGB32;
break;
}
mImageSurface = new gfxImageSurface (format, mWidth, mHeight);
memset(mImageSurface->Data(), 0xFF, mHeight * mImageSurface->Stride());
return NS_OK;
}
nsThebesImage::~nsThebesImage()
{
if (mLockedData)
nsMemory::Free(mLockedData);
if (mLockedAlpha)
nsMemory::Free(mLockedAlpha);
}
PRInt32
nsThebesImage::GetBytesPix()
{
// not including alpha
return 3;
}
PRBool
nsThebesImage::GetIsRowOrderTopToBottom()
{
return PR_TRUE;
}
PRInt32
nsThebesImage::GetWidth()
{
return mWidth;
}
PRInt32
nsThebesImage::GetHeight()
{
return mHeight;
}
PRUint8 *
nsThebesImage::GetBits()
{
//NS_ASSERTION(mLocked == PR_TRUE, "GetBits called outside of Lock!");
return mLockedData;
}
PRInt32
nsThebesImage::GetLineStride()
{
return mWidth * 3;
}
PRBool
nsThebesImage::GetHasAlphaMask()
{
return mAlphaDepth > 0;
}
PRUint8 *
nsThebesImage::GetAlphaBits()
{
//NS_ASSERTION(mLocked == PR_TRUE, "GetAlphaBits called outside of Lock!");
return (PRUint8 *) mLockedAlpha;
}
PRInt32
nsThebesImage::GetAlphaLineStride()
{
return mAlphaDepth == 1 ? (mWidth+7)/8 : mWidth;
}
void
nsThebesImage::ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect)
{
mDecoded.UnionRect(mDecoded, *aUpdateRect);
}
PRBool
nsThebesImage::GetIsImageComplete()
{
return mDecoded == nsRect(0, 0, mWidth, mHeight);
}
nsresult
nsThebesImage::Optimize(nsIDeviceContext* aContext)
{
UpdateFromLockedData();
if (!mOptSurface) {
#ifdef MOZ_ENABLE_GTK2
if (!nsThebesDrawingSurface::UseGlitz()) {
XRenderPictFormat *fmt = nsnull;
if (mRealAlphaDepth == 0) {
fmt = gfxXlibSurface::FindRenderFormat(GDK_DISPLAY(), gfxASurface::ImageFormatRGB24);
} else if (mRealAlphaDepth == 1) {
fmt = gfxXlibSurface::FindRenderFormat(GDK_DISPLAY(), gfxASurface::ImageFormatARGB32);
} else if (mRealAlphaDepth == 8) {
fmt = gfxXlibSurface::FindRenderFormat(GDK_DISPLAY(), gfxASurface::ImageFormatARGB32);
}
/* XXX handle mRealAlphaDepth = 1, and create separate mask */
if (fmt) {
mOptSurface = new gfxXlibSurface(GDK_DISPLAY(),
fmt,
mWidth, mHeight);
}
} else {
# ifdef MOZ_ENABLE_GLITZ
// glitz
nsThebesDeviceContext *tdc = NS_STATIC_CAST(nsThebesDeviceContext*, aContext);
glitz_drawable_format_t *gdf = (glitz_drawable_format_t*) tdc->GetGlitzDrawableFormat();
glitz_drawable_t *gdraw = glitz_glx_create_pbuffer_drawable (GDK_DISPLAY(),
DefaultScreen(GDK_DISPLAY()),
gdf,
mWidth, mHeight);
glitz_format_t *gf =
glitz_find_standard_format (gdraw, GLITZ_STANDARD_ARGB32);
glitz_surface_t *gsurf =
glitz_surface_create (gdraw,
gf,
mWidth,
mHeight,
0,
NULL);
glitz_surface_attach (gsurf, gdraw, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR, 0, 0);
mOptSurface = new gfxGlitzSurface (gdraw, gsurf, PR_TRUE);
# endif
}
#endif
}
if (mOptSurface) {
nsRefPtr<gfxContext> tmpCtx(new gfxContext(mOptSurface));
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
tmpCtx->SetSource(mImageSurface);
#if 0
PRUint32 k = (PRUint32) this;
k |= 0xff000000;
tmpCtx->SetColor(gfxRGBA(nscolor(k)));
#endif
tmpCtx->Paint();
#if 0
tmpCtx->NewPath();
tmpCtx->Rectangle(gfxRect(0, 0, mWidth, mHeight));
tmpCtx->Fill();
#endif
}
return NS_OK;
}
nsColorMap *
nsThebesImage::GetColorMap()
{
return NULL;
}
PRInt8
nsThebesImage::GetAlphaDepth()
{
return mAlphaDepth;
}
void *
nsThebesImage::GetBitInfo()
{
return NULL;
}
NS_IMETHODIMP
nsThebesImage::LockImagePixels(PRBool aMaskPixels)
{
//NS_ASSERTION(!mLocked, "LockImagePixels called on already locked image!");
PRUint32 tmpSize;
// if we already have locked data allocated,
// and we have some data, and we're not up to date,
// then don't bother updating frmo the image surface
// to the 2 buffers -- the 2 buffers are more current,
// because UpdateFromLockedData() hasn't been called yet.
//
// UpdateFromLockedData() is only called right before we
// actually try to draw, because the image decoders
// will call Lock/Unlock pretty frequently as they decode
// rows of the image.
if (mLockedData && mHadAnyData && !mUpToDate)
return NS_OK;
if (mAlphaDepth > 0) {
NS_ASSERTION(mAlphaDepth == 1 || mAlphaDepth == 8,
"Bad alpha depth");
tmpSize = mHeight*(mAlphaDepth == 1 ? ((mWidth+7)/8) : mWidth);
if (!mLockedAlpha)
mLockedAlpha = (PRUint8*)nsMemory::Alloc(tmpSize);
if (!mLockedAlpha)
return NS_ERROR_OUT_OF_MEMORY;
}
tmpSize = mWidth * mHeight * 3;
if (!mLockedData)
mLockedData = (PRUint8*)nsMemory::Alloc(tmpSize);
if (!mLockedData)
return NS_ERROR_OUT_OF_MEMORY;
if (mAlphaDepth > 0 && mHadAnyData) {
// fill from existing ARGB buffer
if (mAlphaDepth == 8) {
PRInt32 destCount = 0;
for (PRInt32 row = 0; row < mHeight; ++row) {
PRUint32* srcRow = (PRUint32*) (mImageSurface->Data() + (mImageSurface->Stride()*row));
for (PRInt32 col = 0; col < mWidth; ++col) {
mLockedAlpha[destCount++] = (PRUint8)(srcRow[col] >> 24);
}
}
} else {
PRInt32 i = 0;
for (PRInt32 row = 0; row < mHeight; ++row) {
PRUint32* srcRow = (PRUint32*) (mImageSurface->Data() + (mImageSurface->Stride()*row));
PRUint8 alphaBits = 0;
for (PRInt32 col = 0; col < mWidth; ++col) {
PRUint8 mask = 1 << (7 - (col&7));
if (srcRow[col] & 0xFF000000) {
alphaBits |= mask;
}
if (mask == 0x01) {
// This mask byte is complete, write it back
mLockedAlpha[i] = alphaBits;
alphaBits = 0;
++i;
}
}
if (mWidth & 7) {
// write back the incomplete alpha mask
mLockedAlpha[i] = alphaBits;
++i;
}
}
}
}
if (mHadAnyData) {
int destCount = 0;
for (PRInt32 row = 0; row < mHeight; ++row) {
PRUint32* srcRow = (PRUint32*) (mImageSurface->Data() + (mImageSurface->Stride()*row));
for (PRInt32 col = 0; col < mWidth; ++col) {
ARGBToThreeChannel(&srcRow[col], &mLockedData[destCount*3]);
destCount++;
}
}
}
mLocked = PR_TRUE;
mOptSurface = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsThebesImage::UnlockImagePixels(PRBool aMaskPixels)
{
//NS_ASSERTION(mLocked, "UnlockImagePixels called on unlocked image!");
mLocked = PR_FALSE;
mUpToDate = PR_FALSE;
return NS_OK;
}
void
nsThebesImage::UpdateFromLockedData()
{
if (!mLockedData || mUpToDate)
return;
mUpToDate = PR_TRUE;
NS_ASSERTION(mAlphaDepth == 0 || mAlphaDepth == 1 || mAlphaDepth == 8,
"Bad alpha depth");
mRealAlphaDepth = 0;
PRInt32 alphaIndex = 0;
PRInt32 lockedBufIndex = 0;
for (PRInt32 row = 0; row < mHeight; ++row) {
PRUint32 *destPtr = (PRUint32*) (mImageSurface->Data() + (row * mImageSurface->Stride()));
for (PRInt32 col = 0; col < mWidth; ++col) {
PRUint8 alpha = 0xFF;
if (mAlphaDepth == 1) {
PRUint8 mask = 1 << (7 - (col&7));
if (!(mLockedAlpha[alphaIndex] & mask)) {
alpha = 0;
}
if (mask == 0x01) {
++alphaIndex;
}
} else if (mAlphaDepth == 8) {
alpha = mLockedAlpha[lockedBufIndex];
}
if (mRealAlphaDepth == 0 && alpha != 0xff)
mRealAlphaDepth = mAlphaDepth;
*destPtr++ =
ThreeChannelToARGB(&mLockedData[lockedBufIndex*3], alpha);
++lockedBufIndex;
}
if (mAlphaDepth == 1) {
if (mWidth & 7) {
++alphaIndex;
}
}
}
if (PR_FALSE) { // Enabling this saves memory but can lead to pathologically bad
// performance. Would also cause problems with premultiply/unpremultiply too
nsMemory::Free(mLockedData);
mLockedData = nsnull;
if (mLockedAlpha) {
nsMemory::Free(mLockedAlpha);
mLockedAlpha = nsnull;
}
}
mHadAnyData = PR_TRUE;
}
/* NB: These are pixels, not twips. */
NS_IMETHODIMP
nsThebesImage::Draw(nsIRenderingContext &aContext, nsIDrawingSurface *aSurface,
PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
{
return Draw(aContext, aSurface, 0, 0, mWidth, mHeight, aX, aY, aWidth, aHeight);
}
/* NB: These are pixels, not twips. */
/* BUT nsRenderingContextImpl's DrawImage calls this with twips. */
NS_IMETHODIMP
nsThebesImage::Draw(nsIRenderingContext &aContext, nsIDrawingSurface *aSurface,
PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight,
PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight)
{
UpdateFromLockedData();
nsThebesRenderingContext *thebesRC = NS_STATIC_CAST(nsThebesRenderingContext*, &aContext);
gfxContext *ctx = thebesRC->Thebes();
#if 0
fprintf (stderr, "nsThebesImage::Draw src [%d %d %d %d] dest [%d %d %d %d] tx [%f %f]\n",
aSX, aSY, aSWidth, aSHeight, aDX, aDY, aDWidth, aDHeight,
ctx->CurrentMatrix().GetTranslation().x, ctx->CurrentMatrix().GetTranslation().y);
#endif
gfxRect sr(aSX, aSY, aSWidth, aSHeight);
gfxRect dr(aDX, aDY, aDWidth, aDHeight);
gfxMatrix mat;
mat.Translate(gfxPoint(aSX, aSY));
mat.Scale(double(aSWidth)/aDWidth, double(aSHeight)/aDHeight);
nsRefPtr<gfxPattern> pat = new gfxPattern(ThebesSurface());
pat->SetMatrix(mat);
ctx->NewPath();
ctx->PixelSnappedRectangleAndSetPattern(dr, pat);
ctx->Fill();
return NS_OK;
}
/* DrawTile is always relative to the device; never relative to the current
* transformation matrix on the device. This is where the IdentityMatrix() bits
* come from.
*/
/* NB: Still pixels! */
NS_IMETHODIMP
nsThebesImage::DrawTile(nsIRenderingContext &aContext,
nsIDrawingSurface *aSurface,
PRInt32 aSXOffset, PRInt32 aSYOffset,
PRInt32 aPadX, PRInt32 aPadY,
const nsRect &aTileRect)
{
UpdateFromLockedData();
nsThebesRenderingContext *thebesRC = NS_STATIC_CAST(nsThebesRenderingContext*, &aContext);
gfxContext *ctx = thebesRC->Thebes();
if (aTileRect.width <= 0 || aTileRect.height <= 0)
return NS_OK;
if (aPadX || aPadY)
fprintf (stderr, "Warning: nsThebesImage::DrawTile given padX(%d)/padY(%d), ignoring\n", aPadX, aPadY);
#if 0
fprintf (stderr, "****** nsThebesImage::DrawTile: (%d,%d [%d, %d]) -> (%d,%d,%d,%d)\n",
aSXOffset, aSYOffset, mWidth, mHeight,
aTileRect.x, aTileRect.y,
aTileRect.width, aTileRect.height);
#endif
gfxMatrix savedMatrix = ctx->CurrentMatrix();
PRBool reallyRepeating = PR_TRUE;
/* Let's figure out if this really is repeating, or if we're just drawing a subrect */
if (aTileRect.x + aTileRect.width > mWidth ||
aTileRect.y + aTileRect.height > mHeight)
{
reallyRepeating = PR_TRUE;
}
ctx->IdentityMatrix();
PRInt32 x0 = aTileRect.x - aSXOffset;
PRInt32 y0 = aTileRect.y - aSYOffset;
ctx->Translate(gfxPoint(x0, y0));
nsRefPtr<gfxPattern> pat = new gfxPattern(ThebesSurface());
if (reallyRepeating)
pat->SetExtend(CAIRO_EXTEND_REPEAT);
ctx->NewPath();
ctx->PixelSnappedRectangleAndSetPattern(gfxRect(aSXOffset, aSYOffset,
aTileRect.width, aTileRect.height),
pat);
ctx->Fill();
ctx->SetMatrix(savedMatrix);
return NS_OK;
}
/* This is only used by the GIF decoder, via gfxImageFrame::DrawTo */
NS_IMETHODIMP
nsThebesImage::DrawToImage(nsIImage* aDstImage, PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight)
{
UpdateFromLockedData();
nsThebesImage *dstThebesImage = NS_STATIC_CAST(nsThebesImage*, aDstImage);
nsRefPtr<gfxContext> dst = new gfxContext(dstThebesImage->ThebesSurface());
dst->NewPath();
// We don't use PixelSnappedRectangleAndSetPattern because if
// these coords aren't already pixel aligned, we've lost
// before we've even begun.
dst->Translate(gfxPoint(aDX, aDY));
dst->Rectangle(gfxRect(0, 0, aDWidth, aDHeight), PR_TRUE);
dst->Scale(double(aDWidth)/mWidth, double(aDHeight)/mHeight);
dst->SetSource(ThebesSurface());
dst->Fill();
return NS_OK;
}
/** Image conversion utils **/
static PRUint8 Unpremultiply(PRUint8 aVal, PRUint8 aAlpha) {
return (aVal*255)/aAlpha;
}
static void ARGBToThreeChannel(PRUint32* aARGB, PRUint8* aData) {
PRUint8 a = (PRUint8)(*aARGB >> 24);
PRUint8 r = (PRUint8)(*aARGB >> 16);
PRUint8 g = (PRUint8)(*aARGB >> 8);
PRUint8 b = (PRUint8)(*aARGB >> 0);
if (a != 0xFF) {
if (a == 0) {
r = 0;
g = 0;
b = 0;
} else {
r = Unpremultiply(r, a);
g = Unpremultiply(g, a);
b = Unpremultiply(b, a);
}
}
#if defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS) || defined(MOZ_WIDGET_PHOTON)
// BGR format; assume little-endian system
#ifndef IS_LITTLE_ENDIAN
#error Strange big-endian/OS combination
#endif
// BGR, blue byte first
aData[0] = b; aData[1] = g; aData[2] = r;
#else
// RGB, red byte first
aData[0] = r; aData[1] = g; aData[2] = b;
#endif
}
static PRUint8 Premultiply(PRUint8 aVal, PRUint8 aAlpha) {
PRUint32 r;
FAST_DIVIDE_BY_255(r, aVal*aAlpha);
return (PRUint8)r;
}
static PRUint32 ThreeChannelToARGB(PRUint8* aData, PRUint8 aAlpha) {
PRUint8 r, g, b;
#if defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS) || defined(MOZ_WIDGET_PHOTON)
// BGR format; assume little-endian system
#ifndef IS_LITTLE_ENDIAN
#error Strange big-endian/OS combination
#endif
// BGR, blue byte first
b = aData[0]; g = aData[1]; r = aData[2];
#else
// RGB, red byte first
r = aData[0]; g = aData[1]; b = aData[2];
#endif
if (aAlpha != 0xFF) {
if (aAlpha == 0) {
r = 0;
g = 0;
b = 0;
} else {
r = Premultiply(r, aAlpha);
g = Premultiply(g, aAlpha);
b = Premultiply(b, aAlpha);
}
}
return (aAlpha << 24) | (r << 16) | (g << 8) | b;
}

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

@ -0,0 +1,119 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 thebes gfx
*
* The Initial Developer of the Original Code is
* mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _NSTHEBESIMAGE_H_
#define _NSTHEBESIMAGE_H_
#include "nsIImage.h"
#include "gfxASurface.h"
#include "gfxImageSurface.h"
class nsThebesImage : public nsIImage
{
public:
nsThebesImage();
~nsThebesImage();
NS_DECL_ISUPPORTS
virtual nsresult Init(PRInt32 aWidth, PRInt32 aHeight,
PRInt32 aDepth, nsMaskRequirements aMaskRequirements);
virtual PRInt32 GetBytesPix();
virtual PRBool GetIsRowOrderTopToBottom();
virtual PRInt32 GetWidth();
virtual PRInt32 GetHeight();
virtual PRUint8 *GetBits();
virtual PRInt32 GetLineStride();
virtual PRBool GetHasAlphaMask();
virtual PRUint8 *GetAlphaBits();
virtual PRInt32 GetAlphaLineStride();
virtual PRBool GetIsImageComplete();
virtual void ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect);
virtual nsresult Optimize(nsIDeviceContext* aContext);
virtual nsColorMap *GetColorMap();
NS_IMETHOD Draw(nsIRenderingContext &aContext,
nsIDrawingSurface *aSurface,
PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight);
NS_IMETHOD Draw(nsIRenderingContext &aContext,
nsIDrawingSurface *aSurface,
PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight,
PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight);
NS_IMETHOD DrawTile(nsIRenderingContext &aContext,
nsIDrawingSurface *aSurface,
PRInt32 aSXOffset, PRInt32 aSYOffset,
PRInt32 aPadX, PRInt32 aPadY,
const nsRect &aTileRect);
NS_IMETHOD DrawToImage(nsIImage* aDstImage,
PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight);
virtual PRInt8 GetAlphaDepth();
virtual void* GetBitInfo();
NS_IMETHOD LockImagePixels(PRBool aMaskPixels);
NS_IMETHOD UnlockImagePixels(PRBool aMaskPixels);
void UpdateFromLockedData();
gfxASurface* ThebesSurface() {
if (mOptSurface)
return mOptSurface;
return mImageSurface;
}
protected:
PRInt32 mWidth;
PRInt32 mHeight;
nsRect mDecoded;
nsRefPtr<gfxImageSurface> mImageSurface;
nsRefPtr<gfxASurface> mOptSurface;
// temporary buffers for Lock()
PRUint8* mLockedData;
PRUint8* mLockedAlpha;
PRUint8 mAlphaDepth;
PRUint8 mRealAlphaDepth;
PRPackedBool mLocked;
PRPackedBool mHadAnyData;
PRPackedBool mUpToDate;
};
#endif /* _NSTHEBESIMAGE_H_ */

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

@ -0,0 +1,212 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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
* mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@pavlov.net>
* Vladimir Vukicevic <vladimir@pobox.com>
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsThebesRegion.h"
NS_IMPL_ISUPPORTS1(nsThebesRegion, nsIRegion)
nsThebesRegion::nsThebesRegion()
{
NS_INIT_ISUPPORTS();
}
nsresult nsThebesRegion::Init (void)
{
mRegion.SetEmpty();
return NS_OK;
}
void nsThebesRegion::SetTo (const nsIRegion &aRegion)
{
const nsThebesRegion* pRegion = NS_STATIC_CAST (const nsThebesRegion*, &aRegion);
mRegion = pRegion->mRegion;
}
void nsThebesRegion::SetTo (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
{
mRegion = nsRect (aX, aY, aWidth, aHeight);
}
void nsThebesRegion::Intersect (const nsIRegion &aRegion)
{
const nsThebesRegion* pRegion = NS_STATIC_CAST (const nsThebesRegion*, &aRegion);
mRegion.And (mRegion, pRegion->mRegion);
}
void nsThebesRegion::Intersect (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
{
mRegion.And (mRegion, nsRect (aX, aY, aWidth, aHeight));
}
void nsThebesRegion::Union (const nsIRegion &aRegion)
{
const nsThebesRegion* pRegion = NS_STATIC_CAST (const nsThebesRegion*, &aRegion);
mRegion.Or (mRegion, pRegion->mRegion);
}
void nsThebesRegion::Union (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
{
mRegion.Or (mRegion, nsRect (aX, aY, aWidth, aHeight));
}
void nsThebesRegion::Subtract (const nsIRegion &aRegion)
{
const nsThebesRegion* pRegion = NS_STATIC_CAST (const nsThebesRegion*, &aRegion);
mRegion.Sub (mRegion, pRegion->mRegion);
}
void nsThebesRegion::Subtract (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
{
mRegion.Sub (mRegion, nsRect (aX, aY, aWidth, aHeight));
}
PRBool nsThebesRegion::IsEmpty (void)
{
return mRegion.IsEmpty ();
}
PRBool nsThebesRegion::IsEqual (const nsIRegion &aRegion)
{
const nsThebesRegion* pRegion = NS_STATIC_CAST (const nsThebesRegion*, &aRegion);
return mRegion.IsEqual (pRegion->mRegion);
}
void nsThebesRegion::GetBoundingBox (PRInt32 *aX, PRInt32 *aY, PRInt32 *aWidth, PRInt32 *aHeight)
{
nsRect BoundRect;
BoundRect = mRegion.GetBounds();
*aX = BoundRect.x;
*aY = BoundRect.y;
*aWidth = BoundRect.width;
*aHeight = BoundRect.height;
}
void nsThebesRegion::Offset (PRInt32 aXOffset, PRInt32 aYOffset)
{
mRegion.MoveBy (aXOffset, aYOffset);
}
PRBool nsThebesRegion::ContainsRect (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
{
nsRegion TmpRegion;
TmpRegion.And (mRegion, nsRect (aX, aY, aWidth, aHeight));
return (!TmpRegion.IsEmpty ());
}
NS_IMETHODIMP
nsThebesRegion::GetRects (nsRegionRectSet **aRects)
{
if (!aRects)
return NS_ERROR_NULL_POINTER;
nsRegionRectSet* pRegionSet = *aRects;
PRUint32 NumRects = mRegion.GetNumRects ();
if (pRegionSet == nsnull) // Not yet allocated
{
PRUint8* pBuf = new PRUint8 [sizeof (nsRegionRectSet) + NumRects * sizeof (nsRegionRect)];
pRegionSet = NS_REINTERPRET_CAST (nsRegionRectSet*, pBuf);
pRegionSet->mRectsLen = NumRects + 1;
} else // Already allocated in previous call
{
if (NumRects > pRegionSet->mRectsLen) // passed array is not big enough - reallocate it.
{
delete [] NS_REINTERPRET_CAST (PRUint8*, pRegionSet);
PRUint8* pBuf = new PRUint8 [sizeof (nsRegionRectSet) + NumRects * sizeof (nsRegionRect)];
pRegionSet = NS_REINTERPRET_CAST (nsRegionRectSet*, pBuf);
pRegionSet->mRectsLen = NumRects + 1;
}
}
pRegionSet->mNumRects = NumRects;
*aRects = pRegionSet;
nsRegionRectIterator ri (mRegion);
nsRegionRect* pDest = &pRegionSet->mRects [0];
const nsRect* pSrc;
while ((pSrc = ri.Next ()))
{
pDest->x = pSrc->x;
pDest->y = pSrc->y;
pDest->width = pSrc->width;
pDest->height = pSrc->height;
pDest++;
}
return NS_OK;
}
NS_IMETHODIMP
nsThebesRegion::FreeRects (nsRegionRectSet *aRects)
{
if (!aRects)
return NS_ERROR_NULL_POINTER;
delete [] NS_REINTERPRET_CAST (PRUint8*, aRects);
return NS_OK;
}
NS_IMETHODIMP
nsThebesRegion::GetNativeRegion (void *&aRegion) const
{
aRegion = 0;
return NS_OK;
}
NS_IMETHODIMP
nsThebesRegion::GetRegionComplexity (nsRegionComplexity &aComplexity) const
{
switch (mRegion.GetNumRects ())
{
case 0: aComplexity = eRegionComplexity_empty; break;
case 1: aComplexity = eRegionComplexity_rect; break;
default: aComplexity = eRegionComplexity_complex; break;
}
return NS_OK;
}
NS_IMETHODIMP
nsThebesRegion::GetNumRects (PRUint32 *aRects) const
{
*aRects = mRegion.GetNumRects ();
return NS_OK;
}

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

@ -0,0 +1,78 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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
* mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@pavlov.net>
* Vladimir Vukicevic <vladimir@pobox.com>
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef NSTHEBESREGION__H__
#define NSTHEBESREGION__H__
#include "nsIRegion.h"
#include "nsRegion.h"
class nsThebesRegion : public nsIRegion
{
public:
nsThebesRegion();
NS_DECL_ISUPPORTS
// nsIRegion
nsresult Init (void);
void SetTo (const nsIRegion &aRegion);
void SetTo (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight);
void Intersect (const nsIRegion &aRegion);
void Intersect (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight);
void Union (const nsIRegion &aRegion);
void Union (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight);
void Subtract (const nsIRegion &aRegion);
void Subtract (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight);
PRBool IsEmpty (void);
PRBool IsEqual (const nsIRegion &aRegion);
void GetBoundingBox (PRInt32 *aX, PRInt32 *aY, PRInt32 *aWidth, PRInt32 *aHeight);
void Offset (PRInt32 aXOffset, PRInt32 aYOffset);
PRBool ContainsRect (PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight);
NS_IMETHOD GetRects (nsRegionRectSet **aRects);
NS_IMETHOD FreeRects (nsRegionRectSet *aRects);
NS_IMETHOD GetNativeRegion (void *&aRegion) const;
NS_IMETHOD GetRegionComplexity (nsRegionComplexity &aComplexity) const;
NS_IMETHOD GetNumRects (PRUint32 *aRects) const;
protected:
nsRegion mRegion;
};
#endif

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -0,0 +1,270 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 thebes gfx
*
* The Initial Developer of the Original Code is
* mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef NSTHEBESRENDERINGCONTEXT__H__
#define NSTHEBESRENDERINGCONTEXT__H__
#include "nsCOMPtr.h"
#include "nsIRenderingContext.h"
#include "nsIDeviceContext.h"
#include "nsIFontMetrics.h"
#include "nsIWidget.h"
#include "nsPoint.h"
#include "nsSize.h"
#include "nsColor.h"
#include "nsRect.h"
#include "nsIRegion.h"
#include "nsTransform2D.h"
#include "nsVoidArray.h"
#include "nsIThebesFontMetrics.h"
#include "nsIThebesRenderingContext.h"
#include "gfxContext.h"
class nsIImage;
class nsThebesDrawingSurface;
class nsThebesRenderingContext : public nsIRenderingContext, public nsIThebesRenderingContext
{
public:
nsThebesRenderingContext();
virtual ~nsThebesRenderingContext();
NS_DECL_ISUPPORTS
NS_IMETHOD Init(nsIDeviceContext* aContext, nsIWidget *aWidget);
NS_IMETHOD Init(nsIDeviceContext* aContext, nsIDrawingSurface *aSurface);
NS_IMETHOD CommonInit(void);
NS_IMETHOD Reset(void);
NS_IMETHOD GetDeviceContext(nsIDeviceContext *& aDeviceContext);
NS_IMETHOD LockDrawingSurface(PRInt32 aX, PRInt32 aY,
PRUint32 aWidth, PRUint32 aHeight,
void **aBits, PRInt32 *aStride,
PRInt32 *aWidthBytes,
PRUint32 aFlags);
NS_IMETHOD UnlockDrawingSurface(void);
NS_IMETHOD SelectOffScreenDrawingSurface(nsIDrawingSurface *aSurface);
NS_IMETHOD GetDrawingSurface(nsIDrawingSurface **aSurface);
NS_IMETHOD GetHints(PRUint32& aResult);
NS_IMETHOD DrawNativeWidgetPixmap(void* aSrcSurfaceBlack,
void* aSrcSurfaceWhite,
const nsIntSize& aSrcSize,
const nsPoint& aDestPos);
NS_IMETHOD PushState(void);
NS_IMETHOD PopState(void);
NS_IMETHOD IsVisibleRect(const nsRect& aRect, PRBool &aIsVisible);
NS_IMETHOD SetClipRect(const nsRect& aRect, nsClipCombine aCombine);
NS_IMETHOD GetClipRect(nsRect &aRect, PRBool &aHasLocalClip);
NS_IMETHOD SetLineStyle(nsLineStyle aLineStyle);
NS_IMETHOD GetLineStyle(nsLineStyle &aLineStyle);
NS_IMETHOD GetPenMode(nsPenMode &aPenMode);
NS_IMETHOD SetPenMode(nsPenMode aPenMode);
NS_IMETHOD SetClipRegion(const nsIRegion& aRegion, nsClipCombine aCombine);
NS_IMETHOD CopyClipRegion(nsIRegion &aRegion);
NS_IMETHOD GetClipRegion(nsIRegion **aRegion);
NS_IMETHOD SetColor(nscolor aColor);
NS_IMETHOD GetColor(nscolor &aColor) const;
NS_IMETHOD SetFont(const nsFont& aFont, nsIAtom* aLangGroup);
NS_IMETHOD SetFont(nsIFontMetrics *aFontMetrics);
NS_IMETHOD GetFontMetrics(nsIFontMetrics *&aFontMetrics);
NS_IMETHOD Translate(nscoord aX, nscoord aY);
NS_IMETHOD Scale(float aSx, float aSy);
NS_IMETHOD GetCurrentTransform(nsTransform2D *&aTransform);
NS_IMETHOD CreateDrawingSurface(const nsRect &aBounds, PRUint32 aSurfFlags, nsIDrawingSurface* &aSurface);
NS_IMETHOD CreateDrawingSurface(nsNativeWidget aWidget, nsIDrawingSurface* &aSurface);
NS_IMETHOD DestroyDrawingSurface(nsIDrawingSurface *aDS);
NS_IMETHOD DrawLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1);
NS_IMETHOD DrawPolyline(const nsPoint aPoints[], PRInt32 aNumPoints);
NS_IMETHOD DrawRect(const nsRect& aRect);
NS_IMETHOD DrawRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
NS_IMETHOD FillRect(const nsRect& aRect);
NS_IMETHOD FillRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
NS_IMETHOD InvertRect(const nsRect& aRect);
NS_IMETHOD InvertRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
NS_IMETHOD FlushRect(const nsRect& aRect);
NS_IMETHOD FlushRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
NS_IMETHOD DrawPolygon(const nsPoint aPoints[], PRInt32 aNumPoints);
NS_IMETHOD FillPolygon(const nsPoint aPoints[], PRInt32 aNumPoints);
NS_IMETHOD DrawEllipse(const nsRect& aRect);
NS_IMETHOD DrawEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
NS_IMETHOD FillEllipse(const nsRect& aRect);
NS_IMETHOD FillEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
NS_IMETHOD DrawArc(const nsRect& aRect,
float aStartAngle, float aEndAngle);
NS_IMETHOD DrawArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
float aStartAngle, float aEndAngle);
NS_IMETHOD FillArc(const nsRect& aRect,
float aStartAngle, float aEndAngle);
NS_IMETHOD FillArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
float aStartAngle, float aEndAngle);
NS_IMETHOD GetWidth(char aC, nscoord &aWidth);
NS_IMETHOD GetWidth(PRUnichar aC, nscoord &aWidth,
PRInt32 *aFontID = nsnull);
NS_IMETHOD GetWidth(const nsString& aString, nscoord &aWidth,
PRInt32 *aFontID = nsnull);
NS_IMETHOD GetWidth(const char* aString, nscoord& aWidth);
NS_IMETHOD GetWidth(const char* aString, PRUint32 aLength,
nscoord& aWidth);
NS_IMETHOD GetWidth(const PRUnichar *aString, PRUint32 aLength,
nscoord &aWidth, PRInt32 *aFontID = nsnull);
NS_IMETHOD GetTextDimensions(const char* aString, PRUint32 aLength,
nsTextDimensions& aDimensions);
NS_IMETHOD GetTextDimensions(const PRUnichar* aString, PRUint32 aLength,
nsTextDimensions& aDimensions, PRInt32* aFontID = nsnull);
NS_IMETHOD PushFilter(const nsRect& aRect, PRBool aAreaIsOpaque, float aOpacity);
NS_IMETHOD PopFilter();
#if defined(_WIN32) || defined(XP_OS2) || defined(MOZ_X11) || defined(XP_BEOS)
NS_IMETHOD GetTextDimensions(const char* aString,
PRInt32 aLength,
PRInt32 aAvailWidth,
PRInt32* aBreaks,
PRInt32 aNumBreaks,
nsTextDimensions& aDimensions,
PRInt32& aNumCharsFit,
nsTextDimensions& aLastWordDimensions,
PRInt32* aFontID = nsnull);
NS_IMETHOD GetTextDimensions(const PRUnichar* aString,
PRInt32 aLength,
PRInt32 aAvailWidth,
PRInt32* aBreaks,
PRInt32 aNumBreaks,
nsTextDimensions& aDimensions,
PRInt32& aNumCharsFit,
nsTextDimensions& aLastWordDimensions,
PRInt32* aFontID = nsnull);
#endif
NS_IMETHOD DrawString(const char *aString, PRUint32 aLength,
nscoord aX, nscoord aY,
const nscoord* aSpacing = nsnull);
NS_IMETHOD DrawString(const PRUnichar *aString, PRUint32 aLength,
nscoord aX, nscoord aY,
PRInt32 aFontID = -1,
const nscoord* aSpacing = nsnull);
NS_IMETHOD DrawString(const nsString& aString, nscoord aX, nscoord aY,
PRInt32 aFontID = -1,
const nscoord* aSpacing = nsnull);
NS_IMETHOD CopyOffScreenBits(nsIDrawingSurface *aSrcSurf,
PRInt32 aSrcX, PRInt32 aSrcY,
const nsRect &aDestBounds,
PRUint32 aCopyFlags);
virtual void* GetNativeGraphicData(GraphicDataType aType);
NS_IMETHOD GetBackbuffer(const nsRect &aRequestedSize,
const nsRect &aMaxSize,
PRBool aForBlending,
nsIDrawingSurface* &aBackbuffer);
NS_IMETHOD ReleaseBackbuffer(void);
NS_IMETHOD DestroyCachedBackbuffer(void);
NS_IMETHOD UseBackbuffer(PRBool* aUseBackbuffer);
NS_IMETHOD PushTranslation(PushedTranslation* aState);
NS_IMETHOD PopTranslation(PushedTranslation* aState);
#ifdef MOZ_MATHML
NS_IMETHOD GetBoundingMetrics(const char* aString, PRUint32 aLength, nsBoundingMetrics& aBoundingMetrics);
NS_IMETHOD GetBoundingMetrics(const PRUnichar* aString, PRUint32 aLength,
nsBoundingMetrics& aBoundingMetrics,
PRInt32* aFontID);
#endif // MOZ_MATHML
NS_IMETHOD DrawImage(imgIContainer *aImage,
const nsRect &aSrcRect,
const nsRect &aDestRect);
NS_IMETHOD DrawTile(imgIContainer *aImage, nscoord aXOffset, nscoord aYOffset,
const nsRect * aTargetRect);
NS_IMETHOD SetRightToLeftText(PRBool aIsRTL) { return NS_OK; }
NS_IMETHOD GetClusterInfo(const PRUnichar *aText,
PRUint32 aLength,
PRUint8 *aClusterStarts);
virtual PRInt32 GetPosition(const PRUnichar *aText,
PRUint32 aLength,
nsPoint aPt);
NS_IMETHOD GetRangeWidth(const PRUnichar *aText,
PRUint32 aLength,
PRUint32 aStart,
PRUint32 aEnd,
PRUint32 &aWidth);
NS_IMETHOD GetRangeWidth(const char *aText,
PRUint32 aLength,
PRUint32 aStart,
PRUint32 aEnd,
PRUint32 &aWidth);
NS_IMETHOD RenderEPS(const nsRect& aRect, FILE *aDataFile);
// Thebes specific stuff
gfxContext *Thebes() { return mThebes; }
nsTransform2D& CurrentTransform();
void TransformCoord (nscoord *aX, nscoord *aY);
nsresult AllocateBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, nsIDrawingSurface* &aBackbuffer, PRBool aCacheBackbuffer, PRUint32 aSurfFlags);
protected:
nsCOMPtr<nsIDeviceContext> mDeviceContext;
// cached pixels2twips, twips2pixels values
double mP2T, mT2P;
nsCOMPtr<nsIWidget> mWidget;
// we need to manage our own clip region (since we can't get at
// the old one from cairo)
nsCOMPtr<nsIThebesFontMetrics> mFontMetrics;
nsLineStyle mLineStyle;
nscolor mColor;
nsRefPtr<gfxContext> mThebes;
nsCOMPtr<nsThebesDrawingSurface> mDrawingSurface;
// for handing out to people
void UpdateTempTransformMatrix();
nsTransform2D mTempTransform;
};
#endif // NSCAIRORENDERINGCONTEXT__H__

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

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

@ -30,4 +30,8 @@ ifeq ($(MOZ_GFX_TOOLKIT),gtk2)
EXPORTS += gfxXlibSurface.h
endif
ifdef MOZ_ENABLE_GLITZ
EXPORTS += gfxGlitzSurface.h
endif
include $(topsrcdir)/config/rules.mk

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

@ -42,10 +42,25 @@
#include "gfxTypes.h"
/**
* A surface is something you can draw on. Instantiate a subclass of this
* abstract class, and use gfxContext to draw on this surface.
*/
class gfxASurface {
THEBES_DECL_REFCOUNTING_ABSTRACT
public:
/**
* The format for an image surface. For all formats with alpha data, 0
* means transparent, 1 or 255 means fully opaque.
*/
typedef enum {
ImageFormatARGB32, ///< ARGB data in native endianness, using premultiplied alpha
ImageFormatRGB24, ///< xRGB data in native endianness
ImageFormatA8, ///< Only an alpha channel
ImageFormatA1 ///< Packed transparency information (one byte refers to 8 pixels)
} gfxImageFormat;
/*** this DOES NOT addref the surface */
cairo_surface_t* CairoSurface() { return mSurface; }

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

@ -42,18 +42,39 @@
#include "gfxTypes.h"
/**
* A color value, storing red, green, blue and alpha components.
* This class does not use premultiplied alpha.
*
* XXX should this use doubles (instead of gfxFloat), for consistency with
* cairo?
*/
struct gfxRGBA {
gfxFloat r, g, b, a;
gfxRGBA() { }
gfxRGBA(const gfxRGBA& c) : r(c.r), g(c.g), b(c.b), a(c.a) {}
/**
* Intialize this color using explicit red, green, blue and alpha
* values.
*/
gfxRGBA(gfxFloat _r, gfxFloat _g, gfxFloat _b, gfxFloat _a=1.0) : r(_r), g(_g), b(_b), a(_a) {}
/**
* Initialize this color from a packed 32-bit color.
* Premultiplied alpha isn't used.
* This uses ABGR byte order in the native endianness.
*
* @see gfxRGBA::Packed
*/
gfxRGBA(PRUint32 c) {
r = ((c >> 0) & 0xff) / 255.0;
g = ((c >> 8) & 0xff) / 255.0;
b = ((c >> 16) & 0xff) / 255.0;
a = ((c >> 24) & 0xff) / 255.0;
}
/**
* Initialize this color by parsing the given string.
*/
gfxRGBA(const char* str) {
a = 1.0;
// if aString[0] is a #, parse it as hex
@ -61,6 +82,11 @@ struct gfxRGBA {
// if aString[0] is a number, parse it loosely as hex
}
/**
* Returns this color value as a packed 32-bit integer. This uses ABGR
* byte order in the native endianness, as accepted by the corresponding
* constructor of this class.
*/
PRUint32 Packed() const {
return (((PRUint8)(a * 255.0) << 24) |
((PRUint8)(b * 255.0) << 16) |
@ -68,6 +94,10 @@ struct gfxRGBA {
((PRUint8)(r * 255.0)));
}
/**
* Convert this color to a hex value. For example, for rgb(255,0,0),
* this will return FF0000.
*/
// XXX I'd really prefer to just have this return an nsACString
// Does this function even make sense, since we're just ignoring the alpha value?
void Hex(nsACString& result) const {

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

@ -53,10 +53,24 @@ class gfxRegion;
class gfxFilter;
class gfxTextRun;
/**
* This is the main class for doing actual drawing. It is initialized using
* a surface and can be drawn on. It manages various state information like
* a current transformation matrix (CTM), a current path, current color,
* etc.
*
* All drawing happens by creating a path and then stroking or filling it.
* The functions like Rectangle and Arc do not do any drawing themselves.
* When a path is drawn (stroked or filled), it is filled/stroked with a
* pattern set by SetPattern, SetColor or SetSource.
*/
class gfxContext {
THEBES_DECL_REFCOUNTING
public:
/**
* Initialize this context from a surface.
*/
gfxContext(gfxASurface *surface);
~gfxContext();
@ -75,27 +89,81 @@ public:
** Paths & Drawing
**/
// these do not consume the current path
/**
* Stroke the current path using the current settings (such as line
* width and color).
* A path is set up using functions such as Line, Rectangle and Arc.
*
* Does not consume the current path.
*/
void Stroke();
/**
* Fill the current path according to the current settings.
*
* Does not consume the current path.
*/
void Fill();
/**
* Forgets the current path.
*/
void NewPath();
/**
* Closes the path, i.e. connects the last drawn point to the first one.
*
* Filling a path will implicitly close it.
*/
void ClosePath();
/**
* Moves the pen to a new point without drawing a line.
*/
void MoveTo(gfxPoint pt);
/**
* Draws a line from the current point to pt.
*
* @see MoveTo
*/
void LineTo(gfxPoint pt);
/**
* Draws a quadratic Bézier curve with control points pt1, pt2 and pt3.
*/
void CurveTo(gfxPoint pt1, gfxPoint pt2, gfxPoint pt3);
// clockwise arc
/**
* Draws a clockwise arc (i.e. a circle segment).
* @param center The center of the circle
* @param radius The radius of the circle
* @param angle1 Starting angle for the segment
* @param angle2 Ending angle
*/
void Arc(gfxPoint center, gfxFloat radius,
gfxFloat angle1, gfxFloat angle2);
// counterclockwise arc
/**
* Draws a counter-clockwise arc (i.e. a circle segment).
* @param center The center of the circle
* @param radius The radius of the circle
* @param angle1 Starting angle for the segment
* @param angle2 Ending angle
*/
void NegativeArc(gfxPoint center, gfxFloat radius,
gfxFloat angle1, gfxFloat angle2);
// path helpers
/**
* Draws a line from start to end.
*/
void Line(gfxPoint start, gfxPoint end); // XXX snapToPixels option?
/**
* Draws the rectangle given by rect.
* @param snapToPixels ?
*/
void Rectangle(gfxRect rect, PRBool snapToPixels = PR_FALSE);
void Ellipse(gfxPoint center, gfxSize dimensions);
void Polygon(const gfxPoint *points, PRUint32 numPoints);
@ -104,56 +172,172 @@ public:
** Text
**/
// Add the text outline to the current path
/**
* Add the text outline to the current path.
*/
void AddStringToPath(gfxTextRun& text, int pos, int len);
// Draw a substring of the text run at the current point
/**
* Draw a substring of the text run at the current point.
*/
void DrawString(gfxTextRun& text, int pos, int len);
/**
** Transformation Matrix manipulation
**/
/**
* Adds a translation to the current matrix. This translation takes place
* before the previously set transformations.
*/
void Translate(gfxPoint pt);
void Scale(gfxFloat x, gfxFloat y);
void Rotate(gfxFloat angle); // radians
// post-multiplies 'other' onto the current CTM
/**
* Adds a scale to the current matrix. This scaling takes place before the
* previously set transformations.
*/
void Scale(gfxFloat x, gfxFloat y);
/**
* Adds a rotation around the origin to the current matrix. This rotation
* takes place before the previously set transformations.
*
* @param angle The angle in radians.
*/
void Rotate(gfxFloat angle);
/**
* Post-multiplies 'other' onto the current CTM, i.e. this
* matrix's transformation will take place before the previously set
* transformations.
*/
void Multiply(const gfxMatrix& other);
/**
* Replaces the current transformation matrix with matrix.
*/
void SetMatrix(const gfxMatrix& matrix);
/**
* Sets the transformation matrix to the identity matrix.
*/
void IdentityMatrix();
/**
* Returns the current transformation matrix.
*/
gfxMatrix CurrentMatrix() const;
/**
* Converts a point from device to user coordinates using the inverse
* transformation matrix.
*/
gfxPoint DeviceToUser(gfxPoint point) const;
/**
* Converts a size from device to user coordinates. This does not apply
* translation components of the matrix.
*/
gfxSize DeviceToUser(gfxSize size) const;
/**
* Converts a rectangle from device to user coordinates; this has the
* same effect as using DeviceToUser on both the rectangle's point and
* size.
*/
gfxRect DeviceToUser(gfxRect rect) const;
/**
* Converts a point from user to device coordinates using the inverse
* transformation matrix.
*/
gfxPoint UserToDevice(gfxPoint point) const;
/**
* Converts a size from user to device coordinates. This does not apply
* translation components of the matrix.
*/
gfxSize UserToDevice(gfxSize size) const;
/**
* Converts a rectangle from user to device coordinates; this has the
* same effect as using DeviceToUser on both the rectangle's point and
* size.
*/
gfxRect UserToDevice(gfxRect rect) const;
/**
* Takes the given rect and tries to align it to device pixels. If
* this succeeds, the method will return PR_TRUE, and the rect will
* be in device coordinates (already transformed by the CTM). If it
* fails, the method will return PR_FALSE, and the rect will not be
* changed.
*/
PRBool UserToDevicePixelSnapped(gfxRect& rect) const;
/**
* Attempts to pixel snap the rectangle, add it to the current
* path, and to set pattern as the current painting source. This
* should be used for drawing filled pixel-snapped rectangles (like
* images), because the CTM at the time of the SetPattern call needs
* to have a snapped translation, or you get smeared images.
*/
void PixelSnappedRectangleAndSetPattern(const gfxRect& rect, gfxPattern *pattern);
/**
** Painting sources
**/
/**
* Uses a solid color for drawing.
*/
void SetColor(const gfxRGBA& c);
/**
* Uses a pattern for drawing.
*/
void SetPattern(gfxPattern *pattern);
void SetSource(gfxASurface *surface) {
SetSource(surface, gfxPoint(0, 0));
}
void SetSource(gfxASurface* surface, gfxPoint offset);
/**
* Uses a surface for drawing. This is a shorthand for creating a
* pattern and setting it.
*
* @param offset ?
*/
void SetSource(gfxASurface* surface, gfxPoint offset = gfxPoint(0.0, 0.0));
/**
** Painting
**/
/**
* Paints the current source surface/pattern everywhere in the current
* clip region.
*/
void Paint(gfxFloat alpha = 1.0);
/**
** Painting with a Mask
**/
/**
* Like Paint, except that it only draws the source where pattern is
* non-transparent.
*/
void Mask(gfxPattern *pattern);
/**
* Shorthand for creating a pattern and calling the pattern-taking
* variant of Mask.
*/
void Mask(gfxASurface *surface, gfxPoint offset = gfxPoint(0.0, 0.0));
/**
** Shortcuts
**/
// Creates a new path with a rectangle from 0,0 to size.w,size.h
// and calls cairo_fill
/**
* Creates a new path with a rectangle from 0,0 to size.w,size.h
* and calls cairo_fill.
*/
void DrawSurface(gfxASurface *surface, gfxSize size);
/**
@ -170,7 +354,16 @@ public:
void SetDash(gfxFloat *dashes, int ndash, gfxFloat offset);
//void getDash() const;
/**
* Sets the line width that's used for line drawing.
*/
void SetLineWidth(gfxFloat width);
/**
* Returns the currently set line width.
*
* @see SetLineWidth
*/
gfxFloat CurrentLineWidth() const;
enum GraphicsLineCap {
@ -178,6 +371,9 @@ public:
LINE_CAP_ROUND,
LINE_CAP_SQUARE
};
/**
* Sets the line caps, i.e. how line endings are drawn.
*/
void SetLineCap(GraphicsLineCap cap);
GraphicsLineCap CurrentLineCap() const;
@ -186,6 +382,10 @@ public:
LINE_JOIN_ROUND,
LINE_JOIN_BEVEL
};
/**
* Sets the line join, i.e. how the connection between two lines is
* drawn.
*/
void SetLineJoin(GraphicsLineJoin join);
GraphicsLineJoin CurrentLineJoin() const;
@ -198,21 +398,30 @@ public:
// define enum for operators (clear, src, dst, etc)
enum GraphicsOperator {
OPERATOR_CLEAR,
OPERATOR_SRC,
OPERATOR_DST,
OPERATOR_OVER,
OPERATOR_OVER_REVERSE,
OPERATOR_IN,
OPERATOR_IN_REVERSE,
OPERATOR_OUT,
OPERATOR_OUT_REVERSE,
OPERATOR_ATOP,
OPERATOR_ATOP_REVERSE,
OPERATOR_XOR,
OPERATOR_ADD,
OPERATOR_SATURATE
OPERATOR_CLEAR = CAIRO_OPERATOR_CLEAR,
OPERATOR_SOURCE = CAIRO_OPERATOR_SOURCE,
OPERATOR_OVER = CAIRO_OPERATOR_OVER,
OPERATOR_IN = CAIRO_OPERATOR_IN,
OPERATOR_OUT = CAIRO_OPERATOR_OUT,
OPERATOR_ATOP = CAIRO_OPERATOR_ATOP,
OPERATOR_DEST = CAIRO_OPERATOR_DEST,
OPERATOR_DEST_OVER = CAIRO_OPERATOR_DEST_OVER,
OPERATOR_DEST_IN = CAIRO_OPERATOR_DEST_IN,
OPERATOR_DEST_OUT = CAIRO_OPERATOR_DEST_OUT,
OPERATOR_DEST_ATOP = CAIRO_OPERATOR_DEST_ATOP,
OPERATOR_XOR = CAIRO_OPERATOR_XOR,
OPERATOR_ADD = CAIRO_OPERATOR_ADD,
OPERATOR_SATURATE = CAIRO_OPERATOR_SATURATE
};
/**
* Sets the operator used for all further drawing. The operator affects
* how drawing something will modify the destination. For example, the
* OVER operator will do alpha blending of source and destination, while
* SOURCE will replace the destination with the source.
*/
void SetOperator(GraphicsOperator op);
GraphicsOperator CurrentOperator() const;
@ -232,11 +441,22 @@ public:
** Clipping
**/
void Clip(); // will clip the last path you've drawn
void ResetClip(); // will remove any clip set
// Helper functions that will create a rect path and call Clip().
// Any current path will be destroyed by these functions!
//
/**
* Clips all further drawing to the current path.
* This does not consume the current path.
*/
void Clip();
/**
* Undoes any clipping. Further drawings will only be restricted by the
* surface dimensions.
*/
void ResetClip();
/**
* Helper functions that will create a rect path and call Clip().
* Any current path will be destroyed by these functions!
*/
void Clip(gfxRect rect); // will clip to a rect
void Clip(const gfxRegion& region); // will clip to a region
@ -249,11 +469,15 @@ public:
FILTER_OPAQUE_DRAW
};
// Start rendering under the filter. We guarantee not to draw outside 'maxArea'.
/**
* Start rendering under the filter. We guarantee not to draw outside 'maxArea'.
*/
void PushFilter(gfxFilter& filter, FilterHints hints, gfxRect& maxArea);
// Completed rendering under the filter, composite what we rendered back to the
// underlying surface using the filter.
/**
* Completed rendering under the filter, composite what we rendered back to the
* underlying surface using the filter.
*/
void PopFilter();
private:

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

@ -40,6 +40,11 @@
#include "gfxTypes.h"
/**
* A filter.
*
* @see gfxContext::PushFilter, gfxContext::PopFilter
*/
class gfxFilter {
static gfxFilter* CreateOpacityFilter(gfxFloat alpha);
// CreateGaussianFilter, etc

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

@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 Oracle Corporation code.
*
* The Initial Developer of the Original Code is Oracle Corporation.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef GFX_GLITZSURFACE_H
#define GFX_GLITZSURFACE_H
#include "gfxASurface.h"
#include <cairo-glitz.h>
/**
* A surface that wraps a glitz surface.
*/
class gfxGlitzSurface : public gfxASurface {
THEBES_DECL_ISUPPORTS_INHERITED
public:
gfxGlitzSurface(glitz_drawable_t *drawable,
glitz_surface_t *glitzSurface,
PRBool takeOwnership = PR_FALSE);
virtual ~gfxGlitzSurface();
/**
* When double-buffering is used, swaps the back and the front buffer.
*/
void SwapBuffers();
unsigned long Width();
unsigned long Height();
glitz_surface_t* GlitzSurface() { return mGlitzSurface; }
glitz_drawable_t* GlitzDrawable() { return mGlitzDrawable; }
protected:
glitz_drawable_t *mGlitzDrawable;
glitz_surface_t *mGlitzSurface;
PRBool mOwnsSurface;
};
#endif /* GFX_GLITZSURFACE_H */

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

@ -43,17 +43,25 @@
// ARGB -- raw buffer.. wont be changed.. good for storing data.
/**
* A raw image buffer. The format can be set in the constructor. Its main
* purpose is for storing read-only images and using it as a source surface,
* but it can also be drawn to.
*/
class gfxImageSurface : public gfxASurface {
THEBES_DECL_ISUPPORTS_INHERITED
public:
typedef enum {
ImageFormatARGB32,
ImageFormatRGB24,
ImageFormatA8,
ImageFormatA1
} gfxImageFormat;
/**
* Construct an image surface.
* @param format Format of the data
* @param width Width of the surface in pixels
* @param height Height in pixels
*
* @see gfxImageFormat
*
* XXX why not unsigned long for the dimensions? And, why not gfxSize?
*/
gfxImageSurface(gfxImageFormat format, long width, long height);
virtual ~gfxImageSurface();
@ -61,7 +69,15 @@ public:
int Format() const { return mFormat; }
long Width() const { return mWidth; }
long Height() const { return mHeight; }
/**
* Distance in bytes between the start of a line and the start of the
* next line.
*/
long Stride() const;
/**
* Returns a pointer for the image data. Users of this function can
* write to it, but must not attempt to free the buffer.
*/
unsigned char* Data() { return mData; } // delete this data under us and die.
private:

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

@ -42,20 +42,44 @@
#include "gfxPoint.h"
#include "gfxTypes.h"
#include "gfxRect.h"
// XX - I don't think this class should use gfxFloat at all,
// but should use 'double' and be called gfxDoubleMatrix;
// we can then typedef that to gfxMatrix where we typedef
// double to be gfxFloat.
/**
* A matrix that represents an affine transformation. Projective
* transformations are not supported. This matrix looks like:
*
* / a b tx \
* | c d ty |
* \ 0 0 1 /
*
* So, transforming a point (x, y) results in:
*
* / a b 0 \ / a * x + c * y + tx \ T
* (x y 1) * | c d 0 | = | b * x + d * y + ty |
* \ tx ty 1 / \ 1 /
*
*/
class gfxMatrix {
protected:
cairo_matrix_t mat;
public:
/**
* Initializes this matrix as the identity matrix.
*/
gfxMatrix() { Reset(); }
gfxMatrix(const gfxMatrix& m) : mat(m.mat) {}
/**
* Initializes the matrix from individual components. See the class
* description for the layout of the matrix.
*/
gfxMatrix(gfxFloat a, gfxFloat b, gfxFloat c, gfxFloat d, gfxFloat tx, gfxFloat ty) {
// XXX cairo_matrix_init?
mat.xx = a; mat.yx = b; mat.xy = c; mat.yy = d; mat.x0 = tx; mat.y0 = ty;
}
@ -68,11 +92,17 @@ public:
return *this;
}
/**
* Post-multiplies m onto the matrix.
*/
const gfxMatrix& operator *= (const gfxMatrix& m) {
return Multiply(m);
}
gfxMatrix operator * (const gfxMatrix& m) {
/**
* Multiplies *this with m and returns the result.
*/
gfxMatrix operator * (const gfxMatrix& m) const {
return gfxMatrix(*this).Multiply(m);
}
@ -94,27 +124,52 @@ public:
}
// matrix operations
/**
* Resets this matrix to the identity matrix.
*/
const gfxMatrix& Reset() {
cairo_matrix_init_identity(&mat);
return *this;
}
/**
* Inverts this matrix, if possible. Otherwise, the matrix is left
* unchanged.
*
* XXX should this do something with the return value of
* cairo_matrix_invert?
*/
const gfxMatrix& Invert() {
cairo_matrix_invert(&mat);
return *this;
}
/**
* Scales this matrix. The scale is pre-multiplied onto this matrix,
* i.e. the scaling takes place before the other transformations.
*/
const gfxMatrix& Scale(gfxFloat x, gfxFloat y) {
cairo_matrix_scale(&mat, x, y);
return *this;
}
/**
* Translates this matrix. The translation is pre-multiplied onto this matrix,
* i.e. the translation takes place before the other transformations.
*/
const gfxMatrix& Translate(const gfxPoint& pt) {
cairo_matrix_translate(&mat, pt.x, pt.y);
return *this;
}
/**
* Rotates this matrix. The rotation is pre-multiplied onto this matrix,
* i.e. the translation takes place after the other transformations.
*
* @param radians Angle in radians.
*/
const gfxMatrix& Rotate(gfxFloat radians) {
// cairo_matrix_rotate?
gfxFloat s = sin(radians);
gfxFloat c = cos(radians);
gfxMatrix t( c, s,
@ -123,27 +178,58 @@ public:
return *this = t.Multiply(*this);
}
/**
* Multiplies the current matrix with m.
* This is a post-multiplication, i.e. the transformations of m are
* applied _after_ the existing transformations.
*
* XXX is that difference (compared to Rotate etc) a good thing?
*/
const gfxMatrix& Multiply(const gfxMatrix& m) {
cairo_matrix_multiply(&mat, &mat, &m.mat);
return *this;
}
void TransformDistance(gfxFloat *dx, gfxFloat *dy) const {
cairo_matrix_transform_distance(&mat, dx, dy);
/**
* Transforms a point according to this matrix.
*/
gfxPoint Transform(const gfxPoint point) const {
gfxPoint ret = point;
cairo_matrix_transform_point(&mat, &ret.x, &ret.y);
return ret;
}
void TransformPoint(gfxFloat *x, gfxFloat *y) const {
cairo_matrix_transform_point(&mat, x, y);
/**
* Transform a distance according to this matrix. This does not apply
* any translation components.
*/
gfxSize Transform(const gfxSize size) const {
gfxSize ret = size;
cairo_matrix_transform_distance(&mat, &ret.width, &ret.height);
return ret;
}
/**
* Transforms both the point and distance according to this matrix.
*/
gfxRect Transform(const gfxRect rect) const {
gfxRect ret(Transform(rect.pos), Transform(rect.size));
return ret;
}
// XXX this is wrong and should go away
gfxSize GetScaling() const {
return gfxSize(mat.xx, mat.yy);
}
/**
* Returns the translation component of this matrix.
*/
gfxPoint GetTranslation() const {
return gfxPoint(mat.x0, mat.y0);
}
// XXX this is wrong and should go away
bool HasShear() const {
return ((mat.xy != 0.0) || (mat.yx != 0.0));
}

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

@ -47,7 +47,19 @@ class gfxWindowsSurface : public gfxASurface {
public:
gfxWindowsSurface(HDC dc);
gfxWindowsSurface(HDC dc, unsigned long width, unsigned long height);
gfxWindowsSurface(unsigned long width, unsigned long height);
virtual ~gfxWindowsSurface();
HDC GetDC() { return mDC; }
private:
PRBool mOwnsDC;
HDC mDC;
HBITMAP mOrigBitmap;
PRInt32 mWidth;
PRInt32 mHeight;
};
#endif /* GFX_WINDOWSSURFACE_H */

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

@ -20,6 +20,7 @@
*
* Contributor(s):
* Stuart Parmenter <pavlov@pavlov.net>
* Vladimir Vukicevic <vladimir@pobox.com>
*
* 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
@ -41,6 +42,7 @@
#include "gfxASurface.h"
#include <cairo-xlib.h>
#include <cairo-xlib-xrender.h>
class gfxXlibSurface : public gfxASurface {
THEBES_DECL_ISUPPORTS_INHERITED
@ -59,6 +61,12 @@ public:
// for the default screen, and attach the given visual
gfxXlibSurface(Display *dpy, Visual *visual, unsigned long width, unsigned long height);
gfxXlibSurface(Display* dpy, Drawable drawable, XRenderPictFormat *format,
unsigned long width, unsigned long height);
gfxXlibSurface(Display* dpy, XRenderPictFormat *format,
unsigned long width, unsigned long height);
virtual ~gfxXlibSurface();
unsigned long Width() { return mWidth; }
@ -67,6 +75,8 @@ public:
Display* XDisplay() { return mDisplay; }
Drawable XDrawable() { return mDrawable; }
static XRenderPictFormat *FindRenderFormat(Display *dpy, gfxImageFormat format);
protected:
PRBool mOwnsPixmap;

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

@ -14,7 +14,8 @@ REQUIRES = \
cairo \
libpixman \
string \
xpcom
xpcom \
$(NULL)
CPPSRCS = \
gfxContext.cpp \
@ -31,6 +32,15 @@ ifeq ($(MOZ_GFX_TOOLKIT),gtk2)
CPPSRCS += gfxXlibSurface.cpp
endif
ifdef MOZ_ENABLE_GLITZ
REQUIRES += glitz
CPPSRCS += gfxGlitzSurface.cpp
ifeq ($(MOZ_GFX_TOOLKIT),gtk2)
REQUIRES += glitzglx
endif
endif
FORCE_STATIC_LIB = 1
# This library is used by other shared libs in a static build
FORCE_USE_PIC = 1

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

@ -20,6 +20,7 @@
*
* Contributor(s):
* Stuart Parmenter <pavlov@pavlov.net>
* Vladimir Vukicevic <vladimir@pobox.com>
*
* 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
@ -120,40 +121,26 @@ void gfxContext::Line(gfxPoint start, gfxPoint end)
LineTo(end);
}
// XXX snapToPixels is only valid when snapping for filled
// rectangles and for even-width stroked rectangles.
// For odd-width stroked rectangles, we need to offset x/y by
// 0.5...
void gfxContext::Rectangle(gfxRect rect, PRBool snapToPixels)
{
if (snapToPixels) {
gfxPoint p1 = UserToDevice(rect.pos);
gfxPoint p2 = UserToDevice(rect.pos + rect.size);
gfxRect snappedRect(rect);
gfxPoint p3 = UserToDevice(rect.pos + gfxSize(rect.size.width, 0.0));
gfxPoint p4 = UserToDevice(rect.pos + gfxSize(0.0, rect.size.height));
if (UserToDevicePixelSnapped(snappedRect)) {
cairo_matrix_t mat;
cairo_get_matrix(mCairo, &mat);
cairo_identity_matrix(mCairo);
Rectangle(snappedRect);
cairo_set_matrix(mCairo, &mat);
if (p1.x != p4.x ||
p2.x != p3.x ||
p1.y != p3.y ||
p2.y != p4.y)
// rectangle is no longer axis-aligned after transforming, so don't snap
goto dontsnap;
cairo_matrix_t mat;
cairo_get_matrix(mCairo, &mat);
if (mat.xx != 1.0 ||
mat.yy != 1.0)
// if we're not at 1.0 scale, don't snap
goto dontsnap;
p1.round();
p2.round();
cairo_identity_matrix(mCairo);
cairo_rectangle(mCairo, p1.x, p1.y, p2.x - p1.x, p2.y - p1.y);
cairo_set_matrix(mCairo, &mat);
return;
return;
}
}
dontsnap:
cairo_rectangle(mCairo, rect.pos.x, rect.pos.y, rect.size.width, rect.size.height);
}
@ -297,6 +284,69 @@ gfxRect gfxContext::UserToDevice(gfxRect rect) const
return ret;
}
PRBool gfxContext::UserToDevicePixelSnapped(gfxRect& rect) const
{
// if we're not at 1.0 scale, don't snap
cairo_matrix_t mat;
cairo_get_matrix(mCairo, &mat);
if (mat.xx != 1.0 || mat.yy != 1.0)
return PR_FALSE;
gfxPoint p1 = UserToDevice(rect.pos);
gfxPoint p2 = UserToDevice(rect.pos + rect.size);
gfxPoint p3 = UserToDevice(rect.pos + gfxSize(rect.size.width, 0.0));
gfxPoint p4 = UserToDevice(rect.pos + gfxSize(0.0, rect.size.height));
// rectangle is no longer axis-aligned after transforming, so we can't snap
if (p1.x != p4.x ||
p2.x != p3.x ||
p1.y != p3.y ||
p2.y != p4.y)
return PR_FALSE;
p1.round();
p2.round();
gfxPoint pd = p2 - p1;
rect.pos = p1;
rect.size = gfxSize(pd.x, pd.y);
return PR_TRUE;
}
void gfxContext::PixelSnappedRectangleAndSetPattern(const gfxRect& rect,
gfxPattern *pattern)
{
gfxRect r(rect);
// Bob attempts to pixel-snap the rectangle, and returns true if
// the snapping succeeds. If it does, we need to set up an
// identity matrix, because the rectangle given back is in device
// coordinates.
//
// We then have to call a translate to dr.pos afterwards, to make
// sure the image lines up in the right place with our pixel
// snapped rectangle.
//
// If snapping wasn't successful, we just translate to where the
// pattern would normally start (in app coordinates) and do the
// same thing.
gfxMatrix mat = CurrentMatrix();
if (UserToDevicePixelSnapped(r)) {
IdentityMatrix();
}
Translate(r.pos);
r.pos.x = r.pos.y = 0;
Rectangle(r);
SetPattern(pattern);
SetMatrix(mat);
}
void gfxContext::SetAntialiasMode(AntialiasMode mode)
{
// XXX implement me
@ -418,6 +468,18 @@ void gfxContext::SetSource(gfxASurface *surface, gfxPoint offset)
cairo_set_source_surface(mCairo, surface->CairoSurface(), offset.x, offset.y);
}
// masking
void gfxContext::Mask(gfxPattern *pattern)
{
cairo_mask(mCairo, pattern->CairoPattern());
}
void gfxContext::Mask(gfxASurface *surface, gfxPoint offset)
{
cairo_mask_surface(mCairo, surface->CairoSurface(), offset.x, offset.y);
}
// fonts?
void gfxContext::DrawString(gfxTextRun& text, int pos, int len)
{

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

@ -0,0 +1,84 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla 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/MPL/
*
* 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 thebes
*
* The Initial Developer of the Original Code is
* mozilla.org
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
*
* 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 MPL, 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 MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "gfxGlitzSurface.h"
THEBES_IMPL_REFCOUNTING(gfxGlitzSurface)
gfxGlitzSurface::gfxGlitzSurface(glitz_drawable_t *drawable, glitz_surface_t *surface, PRBool takeOwnership)
: mGlitzDrawable (drawable), mGlitzSurface(surface), mOwnsSurface(takeOwnership)
{
cairo_surface_t *surf = cairo_glitz_surface_create (mGlitzSurface);
Init(surf);
}
gfxGlitzSurface::~gfxGlitzSurface()
{
Destroy();
if (mOwnsSurface) {
if (mGlitzSurface) {
glitz_surface_flush(mGlitzSurface);
glitz_surface_destroy(mGlitzSurface);
}
if (mGlitzDrawable) {
glitz_drawable_flush(mGlitzDrawable);
glitz_drawable_finish(mGlitzDrawable);
glitz_drawable_destroy(mGlitzDrawable);
}
}
}
void
gfxGlitzSurface::SwapBuffers()
{
glitz_drawable_swap_buffers (GlitzDrawable());
}
unsigned long
gfxGlitzSurface::Width()
{
return glitz_drawable_get_width (GlitzDrawable());
}
unsigned long
gfxGlitzSurface::Height()
{
return glitz_drawable_get_height (GlitzDrawable());
}

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

@ -39,11 +39,44 @@
THEBES_IMPL_REFCOUNTING(gfxWindowsSurface)
gfxWindowsSurface::gfxWindowsSurface(HDC dc)
gfxWindowsSurface::gfxWindowsSurface(HDC dc) :
mOwnsDC(PR_FALSE), mDC(dc), mOrigBitmap(nsnull)
{
Init(cairo_win32_surface_create(dc));
Init(cairo_win32_surface_create(mDC));
}
gfxWindowsSurface::gfxWindowsSurface(HDC dc, unsigned long width, unsigned long height) :
mOwnsDC(PR_TRUE), mWidth(width), mHeight(height)
{
mDC = CreateCompatibleDC(dc);
HBITMAP tbits = nsnull;
if (width > 0 && height > 0)
tbits = CreateCompatibleBitmap(dc, width, height);
else
tbits = CreateCompatibleBitmap(dc, 2, 2);
mOrigBitmap = (HBITMAP)SelectObject(mDC, tbits);
Init(cairo_win32_surface_create(mDC));
}
gfxWindowsSurface::gfxWindowsSurface(unsigned long width, unsigned long height)
{
// Init(cairo_win32_surface_create(dc));
}
gfxWindowsSurface::~gfxWindowsSurface()
{
Destroy();
if (mDC && mOrigBitmap) {
HBITMAP tbits = (HBITMAP)SelectObject(mDC, mOrigBitmap);
if (tbits)
DeleteObject(tbits);
}
if (mOwnsDC)
DeleteDC(mDC);
}

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

@ -36,12 +36,13 @@
*
* ***** END LICENSE BLOCK ***** */
#include <stdio.h>
#include "gfxXlibSurface.h"
THEBES_IMPL_REFCOUNTING(gfxXlibSurface)
gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual) :
mOwnsPixmap(PR_FALSE), mDisplay(dpy), mDrawable(drawable)
gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual)
: mOwnsPixmap(PR_FALSE), mDisplay(dpy), mDrawable(drawable)
{
// figure out width/height/depth
Window root_ignore;
@ -62,15 +63,15 @@ gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual)
}
gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual,
unsigned long width, unsigned long height) :
mOwnsPixmap(PR_FALSE), mDisplay(dpy), mDrawable(drawable), mWidth(width), mHeight(height)
unsigned long width, unsigned long height)
: mOwnsPixmap(PR_FALSE), mDisplay(dpy), mDrawable(drawable), mWidth(width), mHeight(height)
{
cairo_surface_t *surf = cairo_xlib_surface_create(dpy, drawable, visual, width, height);
Init(surf);
}
gfxXlibSurface::gfxXlibSurface(Display* dpy, Visual* visual, unsigned long width, unsigned long height) :
mOwnsPixmap(PR_TRUE), mDisplay(dpy), mWidth(width), mHeight(height)
gfxXlibSurface::gfxXlibSurface(Display* dpy, Visual* visual, unsigned long width, unsigned long height)
: mOwnsPixmap(PR_TRUE), mDisplay(dpy), mWidth(width), mHeight(height)
{
mDrawable = (Drawable)XCreatePixmap(dpy,
@ -82,6 +83,32 @@ gfxXlibSurface::gfxXlibSurface(Display* dpy, Visual* visual, unsigned long width
Init(surf);
}
gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, XRenderPictFormat *format,
unsigned long width, unsigned long height)
: mOwnsPixmap(PR_FALSE), mDisplay(dpy), mDrawable(drawable),
mWidth(width), mHeight(height)
{
cairo_surface_t *surf = cairo_xlib_surface_create_with_xrender_format (dpy, drawable,
ScreenOfDisplay(dpy,DefaultScreen(dpy)),
format, width, height);
Init(surf);
}
gfxXlibSurface::gfxXlibSurface(Display* dpy, XRenderPictFormat *format,
unsigned long width, unsigned long height)
: mOwnsPixmap(PR_TRUE), mDisplay(dpy), mWidth(width), mHeight(height)
{
mDrawable = (Drawable)XCreatePixmap(dpy,
RootWindow(dpy, DefaultScreen(dpy)),
width, height,
format->depth);
cairo_surface_t *surf = cairo_xlib_surface_create_with_xrender_format (dpy, mDrawable,
ScreenOfDisplay(dpy,DefaultScreen(dpy)),
format, width, height);
Init(surf);
}
gfxXlibSurface::~gfxXlibSurface()
{
Destroy();
@ -89,3 +116,24 @@ gfxXlibSurface::~gfxXlibSurface()
if (mOwnsPixmap)
XFreePixmap(mDisplay, mDrawable);
}
XRenderPictFormat*
gfxXlibSurface::FindRenderFormat(Display *dpy, gfxImageFormat format)
{
switch (format) {
case ImageFormatARGB32:
return XRenderFindStandardFormat (dpy, PictStandardARGB32);
break;
case ImageFormatRGB24:
return XRenderFindStandardFormat (dpy, PictStandardRGB24);
break;
case ImageFormatA8:
return XRenderFindStandardFormat (dpy, PictStandardA8);
break;
case ImageFormatA1:
return XRenderFindStandardFormat (dpy, PictStandardA1);
break;
}
return (XRenderPictFormat*)NULL;
}