Compare commits

..

1 Commits

Author SHA1 Message Date
(no author)
fc1b35ec92 This commit was manufactured by cvs2svn to create branch
'TREX_GFXWIDGET_BRANCH'.

git-svn-id: svn://10.0.0.236/branches/TREX_GFXWIDGET_BRANCH@1821 18797224-902f-48f8-a5cc-f745e15eee43
1998-05-18 17:55:36 +00:00
418 changed files with 24341 additions and 106012 deletions

24
mozilla/gfx/Makefile Normal file
View File

@@ -0,0 +1,24 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH = ..
DIRS = src tests
include $(DEPTH)/config/config.mk
include $(DEPTH)/config/rules.mk

Binary file not shown.

22
mozilla/gfx/makefile.win Normal file
View File

@@ -0,0 +1,22 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=..
DIRS= src tests
include <$(DEPTH)\config\rules.mak>

41
mozilla/gfx/src/Makefile Normal file
View File

@@ -0,0 +1,41 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH = ../..
include $(DEPTH)/config/config.mk
LIBRARY_NAME = raptorgfx
MODULE=raptor
REQUIRES=util img xpcom raptor netlib
LCFLAGS=-D_IMPL_NS_GFX
CPPSRCS=nsColor.cpp nsColorNames.cpp nsColorNamesRGB.cpp nsFont.cpp \
nsImageGroup.cpp nsImageManager.cpp nsImageNetContext.cpp \
nsImageRenderer.cpp nsImageRequest.cpp nsImageSystemServices.cpp \
nsImageURL.cpp nsRect.cpp nsTransform2D.cpp nsFontCache.cpp
EXPORTS=nsColor.h nsColorNames.h nsCoord.h nsFont.h nsRect.h nsPoint.h \
nsSize.h nsMargin.h nsTransform2D.h nsIRenderingContext.h \
nsIFontMetrics.h nsIImageManager.h nsIImageGroup.h nsIImageRequest.h \
nsIImageObserver.h nsIDeviceContext.h nsIFontCache.h nsIImage.h \
nsGfxCIID.h
include $(DEPTH)/config/rules.mk

View File

@@ -0,0 +1,79 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=..\..
IGNORE_MANIFEST=1
DIRS = windows
LIBRARY_NAME=gmgfx
MODULE=raptor
REQUIRES=util img xpcom raptor netlib
DEFINES=-D_IMPL_NS_GFX -DWIN32_LEAN_AND_MEAN
CPPSRCS=nsColor.cpp nsColorNames.cpp nsColorNamesRGB.cpp nsFont.cpp \
nsImageGroup.cpp nsImageManager.cpp nsImageNetContext.cpp \
nsImageRenderer.cpp nsImageRequest.cpp nsImageSystemServices.cpp \
nsImageURL.cpp nsRect.cpp nsTransform2D.cpp nsFontCache.cpp
EXPORTS=nsColor.h nsColorNames.h nsCoord.h nsFont.h nsRect.h nsPoint.h \
nsSize.h nsMargin.h nsTransform2D.h nsIRenderingContext.h \
nsIFontMetrics.h nsIImageManager.h nsIImageGroup.h nsIImageRequest.h \
nsIImageObserver.h nsIDeviceContext.h nsIFontCache.h nsIImage.h \
nsGfxCIID.h
CPP_OBJS=.\$(OBJDIR)\nsColor.obj .\$(OBJDIR)\nsColorNames.obj \
.\$(OBJDIR)\nsColorNamesRGB.obj .\$(OBJDIR)\nsFont.obj \
.\$(OBJDIR)\nsImageGroup.obj .\$(OBJDIR)\nsImageManager.obj \
.\$(OBJDIR)\nsImageNetContext.obj .\$(OBJDIR)\nsImageRenderer.obj \
.\$(OBJDIR)\nsImageRequest.obj .\$(OBJDIR)\nsImageSystemServices.obj \
.\$(OBJDIR)\nsImageURL.obj .\$(OBJDIR)\nsRect.obj \
.\$(OBJDIR)\nsTransform2D.obj .\$(OBJDIR)\nsFontCache.obj
LINCS=-I$(PUBLIC)\util -I$(PUBLIC)\img \
-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor \
-I$(PUBLIC)\netlib
MAKE_OBJ_TYPE = DLL
DLLNAME = raptorgfx
DLL=.\$(OBJDIR)\$(DLLNAME).dll
LCFLAGS = \
$(LCFLAGS) \
$(DEFINES) \
$(NULL)
# These are the libraries we need to link with to create the dll
LLIBS= \
$(DIST)\lib\xpcom32.lib \
$(DIST)\lib\raptorbase.lib \
$(DIST)\lib\img3240.lib \
$(DIST)\lib\util.lib \
$(DIST)\lib\libplc21.lib \
$(DIST)\lib\netlib.lib \
$(LIBNSPR)
include <$(DEPTH)\config\rules.mak>
libs:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib
clobber::
rm -f $(DIST)\bin\$(DLLNAME).dll
rm -f $(DIST)\lib\$(DLLNAME).lib

111
mozilla/gfx/src/nsColor.cpp Normal file
View File

@@ -0,0 +1,111 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "plstr.h"
#include "nsColor.h"
#include "nsColorNames.h"
static int ComponentValue(const char* aColorSpec, int dpc)
{
int component = 0;
while (--dpc >= 0) {
char ch = *aColorSpec++;
if ((ch >= '0') && (ch <= '9')) {
component = component*16 + (ch - '0');
} else {
// "ch&7" handles lower and uppercase hex alphabetics
component = component*16 + (ch & 7) + 9;
}
}
return component;
}
// Note: This handles 9 digits of hex to be compatible with eric
// bina's original code. However, it is pickyer with respect to what a
// legal color is and will only return true for perfectly legal color
// values.
NS_GFX PRBool NS_HexToRGB(const char* aColorSpec, nscolor* aResult)
{
NS_PRECONDITION(nsnull != aColorSpec, "null ptr");
if (nsnull == aColorSpec) {
return PR_FALSE;
}
if (aColorSpec[0] == '#') {
aColorSpec++;
}
int nameLen = PL_strlen(aColorSpec);
if ((nameLen == 3) || (nameLen == 6) || (nameLen == 9)) {
// Make sure the digits are legal
for (int i = 0; i < nameLen; i++) {
char ch = aColorSpec[i];
if (((ch >= '0') && (ch <= '9')) ||
((ch >= 'a') && (ch <= 'f')) ||
((ch >= 'A') && (ch <= 'F'))) {
// Legal character
continue;
}
// Whoops. Illegal character.
return PR_FALSE;
}
// Convert the ascii to binary
int dpc = nameLen / 3;
// Translate components from hex to binary
int r = ComponentValue(aColorSpec, dpc);
int g = ComponentValue(aColorSpec + dpc, dpc);
int b = ComponentValue(aColorSpec + dpc*2, dpc);
if (dpc == 1) {
// Scale single digit component to an 8 bit value. Replicate the
// single digit to compute the new value.
r = (r << 4) | r;
g = (g << 4) | g;
b = (b << 4) | b;
} else if (dpc == 3) {
// Drop off the low digit from 12 bit values.
r = r >> 4;
g = g >> 4;
b = b >> 4;
}
NS_ASSERTION((r >= 0) && (r <= 255), "bad r");
NS_ASSERTION((g >= 0) && (g <= 255), "bad g");
NS_ASSERTION((b >= 0) && (b <= 255), "bad b");
if (nsnull != aResult) {
*aResult = NS_RGB(r, g, b);
}
return PR_TRUE;
}
// Improperly formatted color value
return PR_FALSE;
}
PRBool NS_ColorNameToRGB(const char* aColorName, nscolor* aResult)
{
PRInt32 id = nsColorNames::LookupName(aColorName);
if (id >= 0) {
NS_ASSERTION(id < COLOR_MAX, "LookupName mess up");
if (nsnull != aResult) {
*aResult = nsColorNames::kColors[id];
}
return PR_TRUE;
}
return PR_FALSE;
}

52
mozilla/gfx/src/nsColor.h Normal file
View File

@@ -0,0 +1,52 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsColor_h___
#define nsColor_h___
#include "nscore.h"
// A color is a 32 bit unsigned integer with four components: R, G, B
// and A.
typedef PRUint32 nscolor;
// Make a color out of r,g,b values. This assumes that the r,g,b values are
// properly constrained to 0-255. This also assumes that a is 255.
#define NS_RGB(_r,_g,_b) \
((nscolor) ((255 << 24) | ((_b)<<16) | ((_g)<<8) | (_r)))
// Make a color out of r,g,b,a values. This assumes that the r,g,b,a
// values are properly constrained to 0-255.
#define NS_RGBA(_r,_g,_b,_a) \
((nscolor) (((_a) << 24) | ((_b)<<16) | ((_g)<<8) | (_r)))
// Extract color components from nscolor
#define NS_GET_R(_rgba) ((PRUint8) ((_rgba) & 0xff))
#define NS_GET_G(_rgba) ((PRUint8) (((_rgba) >> 8) & 0xff))
#define NS_GET_B(_rgba) ((PRUint8) (((_rgba) >> 16) & 0xff))
#define NS_GET_A(_rgba) ((PRUint8) (((_rgba) >> 24) & 0xff))
// Translate a hex string to a color. Return true if it parses ok,
// otherwise return false.
extern NS_GFX PRBool NS_HexToRGB(const char* aBuf, nscolor* aResult);
// Translate a color name to a color. Return true if it parses ok,
// otherwise return false.
extern NS_GFX PRBool NS_ColorNameToRGB(const char* aBuf, nscolor* aResult);
#endif /* nsColor_h___ */

View File

@@ -0,0 +1,142 @@
/* Do not edit - generated by genhash.pl */
#define COLOR_ALICEBLUE 0
#define COLOR_ANTIQUEWHITE 1
#define COLOR_AQUA 2
#define COLOR_AQUAMARINE 3
#define COLOR_AZURE 4
#define COLOR_BEIGE 5
#define COLOR_BISQUE 6
#define COLOR_BLACK 7
#define COLOR_BLANCHEDALMOND 8
#define COLOR_BLUE 9
#define COLOR_BLUEVIOLET 10
#define COLOR_BROWN 11
#define COLOR_BURLYWOOD 12
#define COLOR_CADETBLUE 13
#define COLOR_CHARTREUSE 14
#define COLOR_CHOCOLATE 15
#define COLOR_CORAL 16
#define COLOR_CORNFLOWERBLUE 17
#define COLOR_CORNSILK 18
#define COLOR_CRIMSON 19
#define COLOR_CYAN 20
#define COLOR_DARKBLUE 21
#define COLOR_DARKCYAN 22
#define COLOR_DARKGOLDENROD 23
#define COLOR_DARKGRAY 24
#define COLOR_DARKGREEN 25
#define COLOR_DARKKHAKI 26
#define COLOR_DARKMAGENTA 27
#define COLOR_DARKOLIVEGREEN 28
#define COLOR_DARKORANGE 29
#define COLOR_DARKORCHID 30
#define COLOR_DARKRED 31
#define COLOR_DARKSALMON 32
#define COLOR_DARKSEAGREEN 33
#define COLOR_DARKSLATEBLUE 34
#define COLOR_DARKSLATEGRAY 35
#define COLOR_DARKTURQUOISE 36
#define COLOR_DARKVIOLET 37
#define COLOR_DEEPPINK 38
#define COLOR_DEEPSKYBLUE 39
#define COLOR_DIMGRAY 40
#define COLOR_DODGERBLUE 41
#define COLOR_FIREBRICK 42
#define COLOR_FLORALWHITE 43
#define COLOR_FORESTGREEN 44
#define COLOR_FUCHSIA 45
#define COLOR_GAINSBORO 46
#define COLOR_GHOSTWHITE 47
#define COLOR_GOLD 48
#define COLOR_GOLDENROD 49
#define COLOR_GRAY 50
#define COLOR_GREEN 51
#define COLOR_GREENYELLOW 52
#define COLOR_HONEYDEW 53
#define COLOR_HOTPINK 54
#define COLOR_INDIANRED 55
#define COLOR_INDIGO 56
#define COLOR_IVORY 57
#define COLOR_KHAKI 58
#define COLOR_LAVENDER 59
#define COLOR_LAVENDERBLUSH 60
#define COLOR_LAWNGREEN 61
#define COLOR_LEMONCHIFFON 62
#define COLOR_LIGHTBLUE 63
#define COLOR_LIGHTCORAL 64
#define COLOR_LIGHTCYAN 65
#define COLOR_LIGHTGOLDENRODYELLOW 66
#define COLOR_LIGHTGREEN 67
#define COLOR_LIGHTGREY 68
#define COLOR_LIGHTPINK 69
#define COLOR_LIGHTSALMON 70
#define COLOR_LIGHTSEAGREEN 71
#define COLOR_LIGHTSKYBLUE 72
#define COLOR_LIGHTSLATEGRAY 73
#define COLOR_LIGHTSTEELBLUE 74
#define COLOR_LIGHTYELLOW 75
#define COLOR_LIME 76
#define COLOR_LIMEGREEN 77
#define COLOR_LINEN 78
#define COLOR_MAGENTA 79
#define COLOR_MAROON 80
#define COLOR_MEDIUMAQUAMARINE 81
#define COLOR_MEDIUMBLUE 82
#define COLOR_MEDIUMORCHID 83
#define COLOR_MEDIUMPURPLE 84
#define COLOR_MEDIUMSEAGREEN 85
#define COLOR_MEDIUMSLATEBLUE 86
#define COLOR_MEDIUMSPRINGGREEN 87
#define COLOR_MEDIUMTURQUOISE 88
#define COLOR_MEDIUMVIOLETRED 89
#define COLOR_MIDNIGHTBLUE 90
#define COLOR_MINTCREAM 91
#define COLOR_MISTYROSE 92
#define COLOR_MOCCASIN 93
#define COLOR_NAVAJOWHITE 94
#define COLOR_NAVY 95
#define COLOR_OLDLACE 96
#define COLOR_OLIVE 97
#define COLOR_OLIVEDRAB 98
#define COLOR_ORANGE 99
#define COLOR_ORANGERED 100
#define COLOR_ORCHID 101
#define COLOR_PALEGOLDENROD 102
#define COLOR_PALEGREEN 103
#define COLOR_PALETURQUOISE 104
#define COLOR_PALEVIOLETRED 105
#define COLOR_PAPAYAWHIP 106
#define COLOR_PEACHPUFF 107
#define COLOR_PERU 108
#define COLOR_PINK 109
#define COLOR_PLUM 110
#define COLOR_POWDERBLUE 111
#define COLOR_PURPLE 112
#define COLOR_RED 113
#define COLOR_ROSYBROWN 114
#define COLOR_ROYALBLUE 115
#define COLOR_SADDLEBROWN 116
#define COLOR_SALMON 117
#define COLOR_SANDYBROWN 118
#define COLOR_SEAGREEN 119
#define COLOR_SEASHELL 120
#define COLOR_SIENNA 121
#define COLOR_SILVER 122
#define COLOR_SKYBLUE 123
#define COLOR_SLATEBLUE 124
#define COLOR_SLATEGRAY 125
#define COLOR_SNOW 126
#define COLOR_SPRINGGREEN 127
#define COLOR_STEELBLUE 128
#define COLOR_TAN 129
#define COLOR_TEAL 130
#define COLOR_THISTLE 131
#define COLOR_TOMATO 132
#define COLOR_TURQUOISE 133
#define COLOR_VIOLET 134
#define COLOR_WHEAT 135
#define COLOR_WHITE 136
#define COLOR_WHITESMOKE 137
#define COLOR_YELLOW 138
#define COLOR_YELLOWGREEN 139
#define COLOR_MAX 140

View File

@@ -0,0 +1,566 @@
/*
** This is a generated file, do not edit it. This file is created by
** genhash.pl
*/
#include "plstr.h"
#include "nsColorNames.h"
#define TOTAL_KEYWORDS 140
#define MIN_WORD_LENGTH 3
#define MAX_WORD_LENGTH 20
#define MIN_HASH_VALUE 5
#define MAX_HASH_VALUE 573
/* maximum key range = 569, duplicates = 0 */
struct StaticNameTable {
char* tag;
PRInt32 id;
};
static const unsigned char kLowerLookup[256] = {
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
64,
97,98,99,100,101,102,103,104,105,106,107,108,109,
110,111,112,113,114,115,116,117,118,119,120,121,122,
91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
};
#define MYLOWER(x) kLowerLookup[((x) & 0x7f)]
/**
* Map a name to an ID or -1
*/
PRInt32 nsColorNames::LookupName(const char* str)
{
static unsigned short asso_values[] =
{
574, 574, 574, 574, 574, 574, 574, 574, 574, 574,
574, 574, 574, 574, 574, 574, 574, 574, 574, 574,
574, 574, 574, 574, 574, 574, 574, 574, 574, 574,
574, 574, 574, 574, 574, 574, 574, 574, 574, 574,
574, 574, 574, 574, 574, 574, 574, 574, 574, 574,
574, 574, 574, 574, 574, 574, 574, 574, 574, 574,
574, 574, 574, 574, 574, 574, 574, 574, 574, 574,
574, 574, 574, 574, 574, 574, 574, 574, 574, 574,
574, 574, 574, 574, 574, 574, 574, 574, 574, 574,
574, 574, 574, 574, 574, 574, 574, 0, 200, 245,
30, 0, 105, 90, 0, 10, 0, 80, 0, 0,
0, 0, 140, 30, 20, 5, 25, 10, 10, 70,
574, 203, 5, 574, 574, 574, 574, 574,
};
static unsigned char lengthtable[] =
{
0, 0, 0, 0, 0, 5, 6, 0, 0, 0, 5, 6, 0, 8,
4, 5, 0, 0, 0, 0, 0, 6, 0, 8, 0, 0, 0, 0,
3, 4, 15, 0, 7, 8, 4, 0, 16, 0, 0, 0, 0, 0,
0, 0, 0, 10, 0, 0, 13, 14, 0, 11, 17, 3, 0, 0,
6, 7, 8, 0, 10, 6, 0, 0, 9, 15, 0, 12, 0, 0,
0, 0, 0, 0, 14, 5, 6, 12, 0, 4, 15, 0, 0, 0,
0, 10, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 6, 0,
0, 9, 0, 0, 7, 0, 0, 5, 6, 0, 0, 0, 0, 0,
0, 0, 0, 5, 6, 7, 13, 9, 0, 0, 0, 0, 4, 5,
0, 0, 0, 9, 0, 11, 0, 0, 0, 0, 0, 7, 0, 9,
0, 0, 0, 13, 4, 0, 0, 0, 0, 9, 10, 0, 0, 0,
4, 10, 6, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 0, 0,
12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
11, 0, 0, 9, 0, 0, 0, 0, 4, 5, 0, 4, 0, 9,
0, 0, 0, 0, 9, 0, 11, 0, 0, 0, 10, 0, 0, 13,
0, 5, 6, 0, 13, 9, 10, 0, 0, 0, 4, 0, 11, 0,
0, 9, 0, 0, 9, 0, 9, 20, 0, 0, 8, 9, 5, 0,
7, 13, 9, 10, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0,
0, 0, 8, 0, 10, 13, 0, 0, 0, 0, 0, 7, 0, 14,
0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 10, 0, 0, 13,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 0, 12,
0, 0, 0, 8, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 12, 0, 0, 0,
11, 0, 0, 0, 0, 0, 12, 0, 0, 10, 0, 0, 8, 6,
0, 8, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 12, 0,
0, 5, 0, 0, 0, 0, 0, 0, 14, 0, 11, 0, 0, 0,
0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 9, 0, 0,
0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0,
0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 8, 0, 0, 14,
0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 10, 9, 0, 0, 0, 0, 9, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
9, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 10,
};
static struct StaticNameTable wordlist[] =
{
{"",}, {"",}, {"",}, {"",}, {"",},
{"olive", 97},
{"maroon", 80},
{"",}, {"",}, {"",},
{"azure", 4},
{"salmon", 117},
{"",},
{"seashell", 120},
{"lime", 76},
{"linen", 78},
{"",}, {"",}, {"",}, {"",}, {"",},
{"sienna", 121},
{"",},
{"moccasin", 93},
{"",}, {"",}, {"",}, {"",},
{"tan", 129},
{"teal", 130},
{"mediumslateblue", 86},
{"",},
{"magenta", 79},
{"seagreen", 119},
{"aqua", 2},
{"",},
{"mediumaquamarine", 81},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"darksalmon", 32},
{"",}, {"",},
{"darkslateblue", 34},
{"mediumseagreen", 85},
{"",},
{"lightsalmon", 70},
{"mediumspringgreen", 87},
{"red", 113},
{"",}, {"",},
{"tomato", 132},
{"thistle", 131},
{"lavender", 59},
{"",},
{"aquamarine", 3},
{"silver", 122},
{"",}, {"",},
{"turquoise", 133},
{"mediumvioletred", 89},
{"",},
{"darkseagreen", 33},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"darkolivegreen", 28},
{"white", 136},
{"violet", 134},
{"antiquewhite", 1},
{"",},
{"snow", 126},
{"mediumturquoise", 88},
{"",}, {"",}, {"",}, {"",},
{"darkviolet", 37},
{"",}, {"",}, {"",}, {"",}, {"",},
{"navajowhite", 94},
{"",}, {"",}, {"",}, {"",},
{"orchid", 101},
{"",}, {"",},
{"indianred", 55},
{"",}, {"",},
{"skyblue", 123},
{"",}, {"",},
{"khaki", 58},
{"indigo", 56},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"green", 51},
{"orange", 99},
{"darkred", 31},
{"darkturquoise", 36},
{"lawngreen", 61},
{"",}, {"",}, {"",}, {"",},
{"gold", 48},
{"wheat", 135},
{"",}, {"",}, {"",},
{"limegreen", 77},
{"",},
{"darkmagenta", 27},
{"",}, {"",}, {"",}, {"",}, {"",},
{"fuchsia", 45},
{"",},
{"darkkhaki", 26},
{"",}, {"",}, {"",},
{"lightseagreen", 71},
{"plum", 110},
{"",}, {"",}, {"",}, {"",},
{"darkgreen", 25},
{"darkorange", 29},
{"",}, {"",}, {"",},
{"peru", 108},
{"lightgreen", 67},
{"purple", 112},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"whitesmoke", 137},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",},
{"hotpink", 54},
{"",},
{"goldenrod", 49},
{"",}, {"",},
{"mediumpurple", 84},
{"darkgoldenrod", 23},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",},
{"floralwhite", 43},
{"",}, {"",},
{"orangered", 100},
{"",}, {"",}, {"",}, {"",},
{"blue", 9},
{"beige", 5},
{"",},
{"navy", 95},
{"",},
{"aliceblue", 0},
{"",}, {"",}, {"",}, {"",},
{"slateblue", 124},
{"",},
{"saddlebrown", 116},
{"",}, {"",}, {"",},
{"ghostwhite", 47},
{"",}, {"",},
{"palevioletred", 105},
{"",},
{"brown", 11},
{"bisque", 6},
{"",},
{"paleturquoise", 104},
{"royalblue", 115},
{"mediumblue", 82},
{"",}, {"",}, {"",},
{"pink", 109},
{"",},
{"forestgreen", 44},
{"",}, {"",},
{"steelblue", 128},
{"",}, {"",},
{"mistyrose", 92},
{"",},
{"lightblue", 63},
{"lightgoldenrodyellow", 66},
{"",}, {"",},
{"darkblue", 21},
{"rosybrown", 114},
{"coral", 16},
{"",},
{"oldlace", 96},
{"lavenderblush", 60},
{"chocolate", 15},
{"blueviolet", 10},
{"",}, {"",}, {"",},
{"palegreen", 103},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"deeppink", 38},
{"",},
{"dodgerblue", 41},
{"darkslategray", 35},
{"",}, {"",}, {"",}, {"",}, {"",},
{"crimson", 19},
{"",},
{"lightsteelblue", 74},
{"",}, {"",}, {"",}, {"",},
{"mintcream", 91},
{"",}, {"",}, {"",}, {"",}, {"",},
{"lightcoral", 64},
{"",}, {"",},
{"palegoldenrod", 102},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",},
{"gainsboro", 46},
{"chartreuse", 14},
{"",},
{"mediumorchid", 83},
{"",}, {"",}, {"",},
{"honeydew", 53},
{"",}, {"",}, {"",}, {"",}, {"",},
{"gray", 50},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",},
{"deepskyblue", 39},
{"",}, {"",},
{"midnightblue", 90},
{"",}, {"",}, {"",},
{"springgreen", 127},
{"",}, {"",}, {"",}, {"",}, {"",},
{"lightskyblue", 72},
{"",}, {"",},
{"darkorchid", 30},
{"",}, {"",},
{"cornsilk", 18},
{"yellow", 138},
{"",},
{"darkgray", 24},
{"",}, {"",},
{"lightpink", 69},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"lemonchiffon", 62},
{"",}, {"",},
{"black", 7},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"lightslategray", 73},
{"",},
{"yellowgreen", 139},
{"",}, {"",}, {"",}, {"",}, {"",},
{"powderblue", 111},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"lightyellow", 75},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",},
{"ivory", 57},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",},
{"cyan", 20},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"olivedrab", 98},
{"",}, {"",}, {"",}, {"",},
{"greenyellow", 52},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"dimgray", 40},
{"",}, {"",}, {"",}, {"",}, {"",},
{"cadetblue", 13},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"darkcyan", 22},
{"",}, {"",},
{"blanchedalmond", 8},
{"",}, {"",},
{"lightcyan", 65},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"sandybrown", 118},
{"peachpuff", 107},
{"",}, {"",}, {"",}, {"",},
{"firebrick", 42},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"slategray", 125},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",},
{"burlywood", 12},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"lightgrey", 68},
{"",}, {"",}, {"",},
{"cornflowerblue", 17},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"papayawhip", 106},
};
if (str != NULL) {
int len = PL_strlen(str);
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) {
register int hval = len;
switch (hval)
{
default:
case 11:
hval += asso_values[MYLOWER(str[10])];
case 10:
case 9:
hval += asso_values[MYLOWER(str[8])];
case 8:
case 7:
hval += asso_values[MYLOWER(str[6])];
case 6:
hval += asso_values[MYLOWER(str[5])];
case 5:
hval += asso_values[MYLOWER(str[4])];
case 4:
case 3:
case 2:
hval += asso_values[MYLOWER(str[1])];
case 1:
hval += asso_values[MYLOWER(str[0])];
break;
}
hval += asso_values[MYLOWER(str[len - 1])];
if (hval <= MAX_HASH_VALUE && hval >= MIN_HASH_VALUE) {
if (len == lengthtable[hval]) {
register const char *tag = wordlist[hval].tag;
/*
** While not at the end of the string, if they ever differ
** they are not equal. We know "tag" is already lower case.
*/
while ((*tag != '\0')&&(*str != '\0')) {
if (*tag != (char) MYLOWER(*str)) {
return -1;
}
tag++;
str++;
}
/*
** One of the strings has ended, if they are both ended, then they
** are equal, otherwise not.
*/
if ((*tag == '\0')&&(*str == '\0')) {
return wordlist[hval].id;
}
}
}
}
}
return -1;
}
const nsColorNames::NameTableEntry nsColorNames::kNameTable[] = {
{ "aliceblue", 0 },
{ "antiquewhite", 1 },
{ "aqua", 2 },
{ "aquamarine", 3 },
{ "azure", 4 },
{ "beige", 5 },
{ "bisque", 6 },
{ "black", 7 },
{ "blanchedalmond", 8 },
{ "blue", 9 },
{ "blueviolet", 10 },
{ "brown", 11 },
{ "burlywood", 12 },
{ "cadetblue", 13 },
{ "chartreuse", 14 },
{ "chocolate", 15 },
{ "coral", 16 },
{ "cornflowerblue", 17 },
{ "cornsilk", 18 },
{ "crimson", 19 },
{ "cyan", 20 },
{ "darkblue", 21 },
{ "darkcyan", 22 },
{ "darkgoldenrod", 23 },
{ "darkgray", 24 },
{ "darkgreen", 25 },
{ "darkkhaki", 26 },
{ "darkmagenta", 27 },
{ "darkolivegreen", 28 },
{ "darkorange", 29 },
{ "darkorchid", 30 },
{ "darkred", 31 },
{ "darksalmon", 32 },
{ "darkseagreen", 33 },
{ "darkslateblue", 34 },
{ "darkslategray", 35 },
{ "darkturquoise", 36 },
{ "darkviolet", 37 },
{ "deeppink", 38 },
{ "deepskyblue", 39 },
{ "dimgray", 40 },
{ "dodgerblue", 41 },
{ "firebrick", 42 },
{ "floralwhite", 43 },
{ "forestgreen", 44 },
{ "fuchsia", 45 },
{ "gainsboro", 46 },
{ "ghostwhite", 47 },
{ "gold", 48 },
{ "goldenrod", 49 },
{ "gray", 50 },
{ "green", 51 },
{ "greenyellow", 52 },
{ "honeydew", 53 },
{ "hotpink", 54 },
{ "indianred", 55 },
{ "indigo", 56 },
{ "ivory", 57 },
{ "khaki", 58 },
{ "lavender", 59 },
{ "lavenderblush", 60 },
{ "lawngreen", 61 },
{ "lemonchiffon", 62 },
{ "lightblue", 63 },
{ "lightcoral", 64 },
{ "lightcyan", 65 },
{ "lightgoldenrodyellow", 66 },
{ "lightgreen", 67 },
{ "lightgrey", 68 },
{ "lightpink", 69 },
{ "lightsalmon", 70 },
{ "lightseagreen", 71 },
{ "lightskyblue", 72 },
{ "lightslategray", 73 },
{ "lightsteelblue", 74 },
{ "lightyellow", 75 },
{ "lime", 76 },
{ "limegreen", 77 },
{ "linen", 78 },
{ "magenta", 79 },
{ "maroon", 80 },
{ "mediumaquamarine", 81 },
{ "mediumblue", 82 },
{ "mediumorchid", 83 },
{ "mediumpurple", 84 },
{ "mediumseagreen", 85 },
{ "mediumslateblue", 86 },
{ "mediumspringgreen", 87 },
{ "mediumturquoise", 88 },
{ "mediumvioletred", 89 },
{ "midnightblue", 90 },
{ "mintcream", 91 },
{ "mistyrose", 92 },
{ "moccasin", 93 },
{ "navajowhite", 94 },
{ "navy", 95 },
{ "oldlace", 96 },
{ "olive", 97 },
{ "olivedrab", 98 },
{ "orange", 99 },
{ "orangered", 100 },
{ "orchid", 101 },
{ "palegoldenrod", 102 },
{ "palegreen", 103 },
{ "paleturquoise", 104 },
{ "palevioletred", 105 },
{ "papayawhip", 106 },
{ "peachpuff", 107 },
{ "peru", 108 },
{ "pink", 109 },
{ "plum", 110 },
{ "powderblue", 111 },
{ "purple", 112 },
{ "red", 113 },
{ "rosybrown", 114 },
{ "royalblue", 115 },
{ "saddlebrown", 116 },
{ "salmon", 117 },
{ "sandybrown", 118 },
{ "seagreen", 119 },
{ "seashell", 120 },
{ "sienna", 121 },
{ "silver", 122 },
{ "skyblue", 123 },
{ "slateblue", 124 },
{ "slategray", 125 },
{ "snow", 126 },
{ "springgreen", 127 },
{ "steelblue", 128 },
{ "tan", 129 },
{ "teal", 130 },
{ "thistle", 131 },
{ "tomato", 132 },
{ "turquoise", 133 },
{ "violet", 134 },
{ "wheat", 135 },
{ "white", 136 },
{ "whitesmoke", 137 },
{ "yellow", 138 },
{ "yellowgreen", 139 },
};

View File

@@ -0,0 +1,44 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsColorNames_h___
#define nsColorNames_h___
#include "nsColor.h"
#include "nsColorNameIDs.h"
class NS_GFX nsColorNames {
public:
// Given a null terminated string of 7 bit characters, return the
// tag id (see nsHTMLTagIDs.h) for the tag or -1 if the tag is not
// known. The lookup function uses a perfect hash.
static PRInt32 LookupName(const char* str);
// Color id to rgb value table
static nscolor kColors[];
struct NameTableEntry {
const char* name;
PRInt32 id;
};
// A table whose index is the id (from LookupName)
static const NameTableEntry kNameTable[];
};
#endif /* nsColorNames_h___ */

View File

@@ -0,0 +1,144 @@
/* Do not edit - generated by tools/Makefile */
#include "nsColorNames.h"
nscolor nsColorNames::kColors[COLOR_MAX] = {
NS_RGB(240, 248, 255),
NS_RGB(250, 235, 215),
NS_RGB( 0, 255, 255),
NS_RGB(127, 255, 212),
NS_RGB(240, 255, 255),
NS_RGB(245, 245, 220),
NS_RGB(255, 228, 196),
NS_RGB( 0, 0, 0),
NS_RGB(255, 235, 205),
NS_RGB( 0, 0, 255),
NS_RGB(138, 43, 226),
NS_RGB(165, 42, 42),
NS_RGB(222, 184, 135),
NS_RGB( 95, 158, 160),
NS_RGB(127, 255, 0),
NS_RGB(210, 105, 30),
NS_RGB(255, 127, 80),
NS_RGB(100, 149, 237),
NS_RGB(255, 248, 220),
NS_RGB(220, 20, 60),
NS_RGB( 0, 255, 255),
NS_RGB( 0, 0, 139),
NS_RGB( 0, 139, 139),
NS_RGB(184, 134, 11),
NS_RGB(169, 169, 169),
NS_RGB( 0, 100, 0),
NS_RGB(189, 183, 107),
NS_RGB(139, 0, 139),
NS_RGB( 85, 107, 47),
NS_RGB(255, 140, 0),
NS_RGB(153, 50, 204),
NS_RGB(139, 0, 0),
NS_RGB(233, 150, 122),
NS_RGB(143, 188, 143),
NS_RGB( 72, 61, 139),
NS_RGB( 47, 79, 79),
NS_RGB( 0, 206, 209),
NS_RGB(148, 0, 211),
NS_RGB(255, 20, 147),
NS_RGB( 0, 191, 255),
NS_RGB(105, 105, 105),
NS_RGB( 30, 144, 255),
NS_RGB(178, 34, 34),
NS_RGB(255, 250, 240),
NS_RGB( 34, 139, 34),
NS_RGB(255, 0, 255),
NS_RGB(220, 220, 220),
NS_RGB(248, 248, 255),
NS_RGB(255, 215, 0),
NS_RGB(218, 165, 32),
NS_RGB(128, 128, 128),
NS_RGB( 0, 128, 0),
NS_RGB(173, 255, 47),
NS_RGB(240, 255, 240),
NS_RGB(255, 105, 180),
NS_RGB(205, 92, 92),
NS_RGB( 75, 0, 130),
NS_RGB(255, 255, 240),
NS_RGB(240, 230, 140),
NS_RGB(230, 230, 250),
NS_RGB(255, 240, 245),
NS_RGB(124, 252, 0),
NS_RGB(255, 250, 205),
NS_RGB(173, 216, 230),
NS_RGB(240, 128, 128),
NS_RGB(224, 255, 255),
NS_RGB(250, 250, 210),
NS_RGB(144, 238, 144),
NS_RGB(211, 211, 211),
NS_RGB(255, 182, 193),
NS_RGB(255, 160, 122),
NS_RGB( 32, 178, 170),
NS_RGB(135, 206, 250),
NS_RGB(119, 136, 153),
NS_RGB(176, 196, 222),
NS_RGB(255, 255, 224),
NS_RGB( 0, 255, 0),
NS_RGB( 50, 205, 50),
NS_RGB(250, 240, 230),
NS_RGB(255, 0, 255),
NS_RGB(128, 0, 0),
NS_RGB(102, 205, 170),
NS_RGB( 0, 0, 205),
NS_RGB(186, 85, 211),
NS_RGB(147, 112, 219),
NS_RGB( 60, 179, 113),
NS_RGB(123, 104, 238),
NS_RGB( 0, 250, 154),
NS_RGB( 72, 209, 204),
NS_RGB(199, 21, 133),
NS_RGB( 25, 25, 112),
NS_RGB(245, 255, 250),
NS_RGB(255, 228, 225),
NS_RGB(255, 228, 181),
NS_RGB(255, 222, 173),
NS_RGB( 0, 0, 128),
NS_RGB(253, 245, 230),
NS_RGB(128, 128, 0),
NS_RGB(107, 142, 35),
NS_RGB(255, 165, 0),
NS_RGB(255, 69, 0),
NS_RGB(218, 112, 214),
NS_RGB(238, 232, 170),
NS_RGB(152, 251, 152),
NS_RGB(175, 238, 238),
NS_RGB(219, 112, 147),
NS_RGB(255, 239, 213),
NS_RGB(255, 218, 185),
NS_RGB(205, 133, 63),
NS_RGB(255, 192, 203),
NS_RGB(221, 160, 221),
NS_RGB(176, 224, 230),
NS_RGB(128, 0, 128),
NS_RGB(255, 0, 0),
NS_RGB(188, 143, 143),
NS_RGB( 65, 105, 225),
NS_RGB(139, 69, 19),
NS_RGB(250, 128, 114),
NS_RGB(244, 164, 96),
NS_RGB( 46, 139, 87),
NS_RGB(255, 245, 238),
NS_RGB(160, 82, 45),
NS_RGB(192, 192, 192),
NS_RGB(135, 206, 235),
NS_RGB(106, 90, 205),
NS_RGB(112, 128, 144),
NS_RGB(255, 250, 250),
NS_RGB( 0, 255, 127),
NS_RGB( 70, 130, 180),
NS_RGB(210, 180, 140),
NS_RGB( 0, 128, 128),
NS_RGB(216, 191, 216),
NS_RGB(255, 99, 71),
NS_RGB( 64, 224, 208),
NS_RGB(238, 130, 238),
NS_RGB(245, 222, 179),
NS_RGB(255, 255, 255),
NS_RGB(245, 245, 245),
NS_RGB(255, 255, 0),
NS_RGB(154, 205, 50),
};

38
mozilla/gfx/src/nsCoord.h Normal file
View File

@@ -0,0 +1,38 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef NSCOORD_H
#define NSCOORD_H
#include "nscore.h"
/*
* Basic type used for the geometry classes. By making it a typedef we can
* easily change it in the future.
*
* All coordinates are maintained as signed 32-bit integers in the twips
* coordinate space. A twip is 1/20th of a point, and there are 72 points per
* inch.
*
* Twips are used because they are a device-independent unit of measure. See
* header file nsUnitConversion.h for many useful macros to convert between
* different units of measure.
*/
typedef PRInt32 nscoord;
#endif /* NSCOORD_H */

View File

@@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsFont.h"
#include "nsString.h"
nsFont::nsFont(const char* aName, PRUint8 aStyle, PRUint8 aVariant,
PRUint16 aWeight, PRUint8 aDecoration, nscoord aSize)
: name(aName)
{
style = aStyle;
variant = aVariant;
weight = aWeight;
decorations = aDecoration;
size = aSize;
}
nsFont::nsFont(const nsString& aName, PRUint8 aStyle, PRUint8 aVariant,
PRUint16 aWeight, PRUint8 aDecoration, nscoord aSize)
: name(aName)
{
style = aStyle;
variant = aVariant;
weight = aWeight;
decorations = aDecoration;
size = aSize;
}
nsFont::nsFont(const nsFont& aOther)
: name(aOther.name)
{
style = aOther.style;
variant = aOther.variant;
weight = aOther.weight;
decorations = aOther.decorations;
size = aOther.size;
}
nsFont::~nsFont()
{
}
PRBool nsFont::Equals(const nsFont& aOther) const
{
if ((style == aOther.style) &&
(variant == aOther.variant) &&
(weight == aOther.weight) &&
(decorations == aOther.decorations) &&
(size == aOther.size) &&
name.EqualsIgnoreCase(aOther.name)) {
return PR_TRUE;
}
return PR_FALSE;
}
nsFont& nsFont::operator=(const nsFont& aOther)
{
name = aOther.name;
style = aOther.style;
variant = aOther.variant;
weight = aOther.weight;
decorations = aOther.decorations;
size = aOther.size;
return *this;
}

86
mozilla/gfx/src/nsFont.h Normal file
View File

@@ -0,0 +1,86 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsFont_h___
#define nsFont_h___
#include "nscore.h"
#include "nsCoord.h"
#include "nsString.h"
// XXX we need a method to enumerate all of the possible fonts on the
// system across family, weight, style, size, etc. But not here!
// Font structure.
struct NS_GFX nsFont {
// The family name of the font
nsString name;
// The style of font (normal, italic, oblique)
PRUint8 style;
// The variant of the font (normal, small-caps)
PRUint8 variant;
// The weight of the font (0-999)
PRUint16 weight;
// The decorations on the font (underline, overline,
// line-through). The decorations can be binary or'd together.
PRUint8 decorations;
// The size of the font, in nscoord units
nscoord size;
// Initialize the font struct with an iso-latin1 name
nsFont(const char* aName, PRUint8 aStyle, PRUint8 aVariant,
PRUint16 aWeight, PRUint8 aDecoration, nscoord aSize);
// Initialize the font struct with a (potentially) unicode name
nsFont(const nsString& aName, PRUint8 aStyle, PRUint8 aVariant,
PRUint16 aWeight, PRUint8 aDecoration, nscoord aSize);
// Make a copy of the given font
nsFont(const nsFont& aFont);
~nsFont();
PRBool operator==(const nsFont& aOther) const {
return Equals(aOther);
}
PRBool Equals(const nsFont& aOther) const ;
nsFont& operator=(const nsFont& aOther);
};
#define NS_FONT_STYLE_NORMAL 0
#define NS_FONT_STYLE_ITALIC 1
#define NS_FONT_STYLE_OBLIQUE 2
#define NS_FONT_VARIANT_NORMAL 0
#define NS_FONT_VARIANT_SMALL_CAPS 1
#define NS_FONT_DECORATION_UNDERLINE 0x1
#define NS_FONT_DECORATION_OVERLINE 0x2
#define NS_FONT_DECORATION_LINE_THROUGH 0x4
#define NS_FONT_WEIGHT_NORMAL 400
#define NS_FONT_WEIGHT_BOLD 700
#endif /* nsFont_h___ */

View File

@@ -0,0 +1,139 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsIFontCache.h"
#include "nsFont.h"
#include "nsVoidArray.h"
#include "nsIFontMetrics.h"
#include "nsIDeviceContext.h"
#include "nsGfxCIID.h"
static NS_DEFINE_IID(kIFontCacheIID, NS_IFONT_CACHE_IID);
class FontCacheImpl : public nsIFontCache
{
public:
FontCacheImpl();
~FontCacheImpl();
NS_DECL_ISUPPORTS
virtual nsresult Init(nsIDeviceContext* aContext);
virtual nsIDeviceContext* GetDeviceContext() const;
virtual nsIFontMetrics* GetMetricsFor(const nsFont& aFont);
virtual void Flush();
protected:
nsVoidArray mFontMetrics;
nsIDeviceContext *mContext;
};
FontCacheImpl :: FontCacheImpl()
{
NS_INIT_REFCNT();
mContext = nsnull;
}
FontCacheImpl :: ~FontCacheImpl()
{
Flush();
NS_IF_RELEASE(mContext);
}
NS_IMPL_ISUPPORTS(FontCacheImpl, kIFontCacheIID)
nsresult FontCacheImpl :: Init(nsIDeviceContext* aContext)
{
NS_PRECONDITION(nsnull != aContext, "null ptr");
mContext = aContext;
NS_ADDREF(mContext);
return NS_OK;
}
nsIDeviceContext* FontCacheImpl::GetDeviceContext() const
{
NS_IF_ADDREF(mContext);
return mContext;
}
nsIFontMetrics* FontCacheImpl :: GetMetricsFor(const nsFont& aFont)
{
nsIFontMetrics* fm;
// First check our cache
PRInt32 n = mFontMetrics.Count();
for (PRInt32 cnt = 0; cnt < n; cnt++)
{
fm = (nsIFontMetrics*) mFontMetrics.ElementAt(cnt);
if (aFont.Equals(fm->GetFont()))
{
NS_ADDREF(fm);
return fm;
}
}
// It's not in the cache. Get font metrics and then cache them.
static NS_DEFINE_IID(kFontMetricsCID, NS_FONT_METRICS_CID);
static NS_DEFINE_IID(kFontMetricsIID, NS_IFONT_METRICS_IID);
nsresult rv = NSRepository::CreateInstance(kFontMetricsCID, nsnull,
kFontMetricsIID, (void **)&fm);
if (NS_OK != rv)
return nsnull;
rv = fm->Init(aFont, mContext);
if (NS_OK != rv)
return nsnull;/* XXX losing error code */
mFontMetrics.AppendElement(fm);
NS_ADDREF(fm);
return fm;
}
void FontCacheImpl::Flush()
{
PRInt32 i, n = mFontMetrics.Count();
for (i = 0; i < n; i++) {
nsIFontMetrics* fm = (nsIFontMetrics*) mFontMetrics.ElementAt(i);
NS_RELEASE(fm);
}
mFontMetrics.Clear();
}
NS_GFX nsresult
NS_NewFontCache(nsIFontCache **aInstancePtrResult)
{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
if (nsnull == aInstancePtrResult)
return NS_ERROR_NULL_POINTER;
nsIFontCache *cache = new FontCacheImpl();
if (nsnull == cache)
return NS_ERROR_OUT_OF_MEMORY;
return cache->QueryInterface(kIFontCacheIID, (void **) aInstancePtrResult);
}

View File

@@ -0,0 +1,42 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsGfxCIID_h__
#define nsGfxCIID_h__
#include "nsISupports.h"
#include "nsIFactory.h"
#include "nsRepository.h"
#define NS_IMAGE_CID \
{ 0x6049b260, 0xc1e6, 0x11d1, \
{ 0xa8, 0x27, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }
#define NS_RENDERING_CONTEXT_CID \
{ 0x6049b261, 0xc1e6, 0x11d1, \
{ 0xa8, 0x27, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }
#define NS_DEVICE_CONTEXT_CID \
{ 0x6049b262, 0xc1e6, 0x11d1, \
{ 0xa8, 0x27, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }
#define NS_FONT_METRICS_CID \
{ 0x6049b263, 0xc1e6, 0x11d1, \
{ 0xa8, 0x27, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }
#endif

View File

@@ -0,0 +1,92 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsIDeviceContext_h___
#define nsIDeviceContext_h___
#include "nsISupports.h"
#include "nsIRenderingContext.h"
#include "nsCoord.h"
#include "nsRect.h"
class nsIView;
class nsIRenderingContext;
class nsIFontCache;
class nsIFontMetrics;
class nsIWidget;
struct nsFont;
#define NS_IDEVICE_CONTEXT_IID \
{ 0x5931c580, 0xb917, 0x11d1, \
{ 0xa8, 0x24, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }
class nsIDeviceContext : public nsISupports
{
public:
virtual nsresult Init() = 0;
virtual nsIRenderingContext * CreateRenderingContext(nsIView *aView) = 0;
virtual void InitRenderingContext(nsIRenderingContext *aContext, nsIWidget *aWindow) = 0;
//these are queries to figure out how large an output unit
//(i.e. pixel) is in terms of twips (1/20 of a point)
virtual float GetDevUnitsToTwips() const = 0;
virtual float GetTwipsToDevUnits() const = 0;
//these are set by the object that created this
//device context to define what the scale is
//between the units used by the app and the
//device units
virtual void SetAppUnitsToDevUnits(float aAppUnits) = 0;
virtual void SetDevUnitsToAppUnits(float aDevUnits) = 0;
//these are used to query the scale values defined
//by the above Set*() methods
virtual float GetAppUnitsToDevUnits() const = 0;
virtual float GetDevUnitsToAppUnits() const = 0;
virtual float GetScrollBarWidth() const = 0;
virtual float GetScrollBarHeight() const = 0;
//be sure to Relase() after you are done with the Get()
virtual nsIFontCache * GetFontCache() = 0;
virtual void FlushFontCache() = 0;
// Get the font metrics for a given font.
virtual nsIFontMetrics* GetMetricsFor(const nsFont& aFont) = 0;
//get and set the document zoom value used for display-time
//scaling. default is 1.0 (no zoom)
virtual void SetZoom(float aZoom) = 0;
virtual float GetZoom() const = 0;
//get a low level drawing surface for rendering. the rendering context
//that is passed in is used to create the drawing surface if there isn't
//already one in the device context. the drawing surface is then cached
//in the device context for re-use.
virtual nsDrawingSurface GetDrawingSurface(nsIRenderingContext &aContext) = 0;
//functions for handling gamma correction of output device
virtual float GetGamma(void) = 0;
virtual void SetGamma(float aGamma) = 0;
//XXX the return from this really needs to be ref counted somehow. MMP
virtual PRUint8 * GetGammaTable(void) = 0;
};
#endif /* nsIDeviceContext_h___ */

View File

@@ -0,0 +1,68 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsIFontCache_h___
#define nsIFontCache_h___
#include <stdio.h>
#include "nscore.h"
#include "nsISupports.h"
class nsIFontMetrics;
class nsIDeviceContext;
struct nsFont;
// IID for the nsIFontCache interface
#define NS_IFONT_CACHE_IID \
{ 0x894758e0, 0xb49a, 0x11d1, \
{ 0xa8, 0x24, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }
/**
* Font cache interface. A font cache is bound to a particular device
* context which it uses to realize the font metrics. The cache uses
* the nsFont as a key.
*/
class nsIFontCache : public nsISupports
{
public:
/**
* Initialize the font cache. Call this after creating the font
* cache and before trying to use it.
*/
virtual nsresult Init(nsIDeviceContext* aContext) = 0;
/**
* Get the device context associated with this cache
*/
virtual nsIDeviceContext* GetDeviceContext() const = 0;
/**
* Get metrics for a given font.
*/
virtual nsIFontMetrics* GetMetricsFor(const nsFont& aFont) = 0;
/**
* Flush the cache.
*/
virtual void Flush() = 0;
};
extern NS_GFX nsresult
NS_NewFontCache(nsIFontCache **aInstancePtrResult);
#endif

View File

@@ -0,0 +1,87 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsIFontMetrics_h___
#define nsIFontMetrics_h___
#include "nsISupports.h"
#include "nsCoord.h"
struct nsFont;
class nsString;
class nsIDeviceContext;
// IID for the nsIFontMetrics interface
#define NS_IFONT_METRICS_IID \
{ 0xc74cb770, 0xa33e, 0x11d1, \
{ 0xa8, 0x24, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }
//----------------------------------------------------------------------
// Native font handle
typedef void* nsFontHandle;
// FontMetrics interface
class nsIFontMetrics : public nsISupports
{
//what about encoding, where do we put that? MMP
public:
//initializer
virtual nsresult Init(const nsFont& aFont, nsIDeviceContext* aContext) = 0;
//get the width of an 8 bit char
virtual nscoord GetWidth(char aC) = 0;
//get the width of a unicode char
virtual nscoord GetWidth(PRUnichar aC) = 0;
//get the width of an nsString
virtual nscoord GetWidth(const nsString& aString) = 0;
//get the width of 8 bit character string
virtual nscoord GetWidth(const char *aString) = 0;
//get the width of a Unicode character string
virtual nscoord GetWidth(const PRUnichar *aString, PRUint32 aLength) = 0;
//get the height as this font
virtual nscoord GetHeight() = 0;
//get height - (ascent + descent)
virtual nscoord GetLeading() = 0;
//get the maximum character ascent
virtual nscoord GetMaxAscent() = 0;
//get the maximum character descent
virtual nscoord GetMaxDescent() = 0;
//get the maximum character advance for the font
virtual nscoord GetMaxAdvance() = 0;
//get the widths of the first 256 characters of the font
virtual const nscoord *GetWidths() = 0;
//get the font associated width these metrics
virtual const nsFont& GetFont() = 0;
virtual nsFontHandle GetFontHandle() = 0;
};
#endif /* nsIFontMetrics_h___ */

233
mozilla/gfx/src/nsIImage.h Normal file
View File

@@ -0,0 +1,233 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsIImage_h___
#define nsIImage_h___
#include "nsISupports.h"
#include "nsRect.h"
#include "nsIRenderingContext.h"
typedef struct
{
//I lifted this from the image lib. The difference is that
//this uses nscolor instead of NI_RGB. Multiple color pollution
//is a bad thing. MMP
PRInt32 NumColors; // Number of colors in the colormap.
// A negative value can be used to denote a
// possibly non-unique set.
//nscolor *Map; // Colormap colors.
PRUint8 *Index; // NULL, if map is in index order, otherwise
// specifies the indices of the map entries. */
} nsColorMap;
typedef enum {
nsMaskRequirements_kNoMask,
nsMaskRequirements_kNeeds1Bit,
nsMaskRequirements_kNeeds8Bit
} nsMaskRequirements;
typedef enum{
nsHighQual,
nsMedQual,
nsLowQual
}nsBlendQuality;
#define nsImageUpdateFlags_kColorMapChanged 0x1
#define nsImageUpdateFlags_kBitsChanged 0x2
// IID for the nsIImage interface
#define NS_IIMAGE_IID \
{ 0x0b4faaa0, 0xaa3a, 0x11d1, \
{ 0xa8, 0x24, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }
// Interface to Images
class nsIImage : public nsISupports
{
public:
/**
* Build and initialize the pixelmap
* @param aWidth The width in pixels of the desired pixelmap
* @param aHeight The height in pixels of the desired pixelmap
* @param aDepth The number of bits per pixel for the pixelmap
* @param aMaskRequirements A flag indicating if a alpha mask should be allocated
*/
virtual nsresult Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequirements aMaskRequirements) = 0;
/**
* Get the width for the pixelmap
@return The width in pixels for the pixelmap
*/
virtual PRInt32 GetWidth() = 0;
/**
* Get the height for the pixelmap
@return The height in pixels for the pixelmap
*/
virtual PRInt32 GetHeight() = 0;
/**
* Get a pointer to the bits for the pixelmap, only if it is not optimized
@return address of the DIB pixel array
*/
virtual PRUint8 * GetBits() = 0;
/**
* Get the number of bytes needed to get to the next scanline for the pixelmap
@return The number of bytes in each scanline
*/
virtual PRInt32 GetLineStride() = 0;
/**
* Get a pointer to the bits for the alpha mask
@return address of the alpha mask pixel array
*/
virtual PRUint8 * GetAlphaBits() = 0;
/**
* Get the width of the alpha mask
@return The width in pixels
*/
virtual PRInt32 GetAlphaWidth() = 0;
/**
* Get the height of the alpha mask
@return The width in pixels
*/
virtual PRInt32 GetAlphaHeight() = 0;
/**
* Get the x location of the upper corner of the alpha mask
@return The x location in pixels
*/
virtual PRInt32 GetAlphaXLoc() = 0;
/**
* Get the y location of the upper corner of the alpha mask
@return The y location in pixels
*/
virtual PRInt32 GetAlphaYLoc() = 0;
/**
* Get the number of bytes needed to get to the next scanline for the alpha mask
@return The number of bytes in each scanline
*/
virtual PRInt32 GetAlphaLineStride() = 0;
/**
* Will update a pixelmaps color table
@param aFlags Used to pass in parameters for the update
@param aUpdateRect The rectangle to update
*/
virtual void ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect) = 0;
/**
* Returns if the pixelmap has been converted to an optimized pixelmap
@return If true, it is optimized
*/
virtual PRBool IsOptimized() = 0;
/**
* Converted this pixelmap to an optimized pixelmap for the device
@param aSurface The surface to optimize for
@return the result of the operation, if NS_OK, then the pixelmap is optimized
*/
virtual nsresult Optimize(nsDrawingSurface aSurface) = 0;
/**
* Get the colormap for the pixelmap
@return if non null, the colormap for the pixelmap,otherwise the image is not color mapped
*/
virtual nsColorMap * GetColorMap() = 0;
/**
* BitBlit the pixelmap to a device, the source can be scale to the dest
@param aSurface the surface to blit to
@param aX The destination horizontal location
@param aY The destination vertical location
@param aWidth The destination width of the pixelmap
@param aHeight The destination height of the pixelmap
@return if TRUE, no errors
*/
virtual PRBool Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface, PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) = 0;
/**
* BitBlit the pixelmap to a device, the source and dest can be scaled
* @param aSurface the surface to blit to
* @param aSX The source width of the pixelmap
* @param aSY The source vertical location
* @param aSWidth The source width of the pixelmap
* @param aSHeight The source height of the pixelmap
* @param aDX The destination horizontal location
* @param aDY The destination vertical location
* @param aDWidth The destination width of the pixelmap
* @param aDHeight The destination height of the pixelmap
* @return if TRUE, no errors
*/
virtual PRBool Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface, PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight,
PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight) = 0;
/**
* Composite this image with the passed in image using the alpha mask
* @param aTheImage The image to blend into this image
* @param aULLocation The upper left coordinate to place the passed in image
*/
virtual void CompositeImage(nsIImage *aTheImage,nsPoint *aULLocation,nsBlendQuality aQuality) = 0;
/**
* Build an alpha mask using this image
* @param aTheMaskImage The image to build the mask from
* @return true if the mask was set up.
*/
virtual PRBool SetAlphaMask(nsIImage *aTheMask) = 0;
/**
* Move the alpha mask to this absolute location
* @param the horiztonal location
* @param the vertical location
*/
virtual void MoveAlphaMask(PRInt32 aX, PRInt32 aY) = 0;
/**
* Duplicate this image and pass back new object to it
* @param TheImage is the image to duplicate into this object
* @return the new image
*/
virtual nsIImage* DuplicateImage() = 0;
//get the color space metrics for this image
//virtual NI_ColorSpec * GetColorSpec() = 0; fix
//get the color which should be considered transparent.
//if this image is color mapped, this value will be an
//index into the color map. hokey? yes, but it avoids
//another silly api or struct.
//virtual nscolor GetTransparentColor() = 0; fix.
};
//change notification API flag bits
#define NS_IMAGE_UPDATE_COLORMAP 1
#define NS_IMAGE_UPDATE_PIXELS 2
#define NS_IMAGE_UPDATE_ALPHA 4
#endif

View File

@@ -0,0 +1,118 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsIImageGroup_h___
#define nsIImageGroup_h___
#include <stdio.h>
#include "nsISupports.h"
#include "nscore.h"
#include "nsColor.h"
class nsIImageGroupObserver;
class nsIImageRequestObserver;
class nsIImageRequest;
class nsIRenderingContext;
/** For important images, like backdrops. */
#define nsImageLoadFlags_kHighPriority 0x01
/** Don't throw this image out of cache. */
#define nsImageLoadFlags_kSticky 0x02
/** Don't get image out of image cache. */
#define nsImageLoadFlags_kBypassCache 0x04
/** Don't load if image cache misses. */
#define nsImageLoadFlags_kOnlyFromCache 0x08
// IID for the nsIImageGroup interface
#define NS_IIMAGEGROUP_IID \
{ 0xbe927e40, 0xaeaa, 0x11d1, \
{ 0x9b, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
/**
*
* Image group. A convenient way to group a set of image load requests
* and control them as a group.
*/
class nsIImageGroup : public nsISupports
{
public:
/**
* Initialize an image group with a rendering context. All images
* in this group will be decoded for the specified rendering context.
*/
virtual nsresult Init(nsIRenderingContext *aRenderingContext) = 0;
/**
* Add an observers to be informed of image group notifications.
*
* @param aObserver - An observer to add to the observer list.
* @param boolean indicating whether addition was successful.
*/
virtual PRBool AddObserver(nsIImageGroupObserver *aObserver) = 0;
/**
* Remove a previously added observer from the observer list.
*
* @param aObserver - An observer to remove from the observer list.
* @param boolean indicating whether the removal was successful.
*/
virtual PRBool RemoveObserver(nsIImageGroupObserver *aObserver) = 0;
/**
* Fetch the image corresponding to the specified URL.
*
* @param aUrl - the URL of the image to be loaded.
* @param aObserver - the observer is notified at significant
* points in image loading.
* @param aWidth, aHeight - These parameters specify the target
* dimensions of the image. The image will be stretched
* horizontally, vertically or both to meet these parameters.
* If both width and height are zero, the image is decoded
* using its "natural" size. If only one of width and height
* is zero, the image is scaled to the provided dimension, with
* the unspecified dimension scaled to maintain the image's
* original aspect ratio.
* @param aBackgroundColor - If the background color is NULL, a mask
* will be generated for any transparent images. If background
* color is non-NULL, it indicates the RGB value to be painted
* into the image for "transparent" areas of the image, in which
* case no mask is created. This is intended for backdrops and
* printing.
* @param aFlags - image loading flags are specified above
*
* @return the resulting image request object.
*/
virtual nsIImageRequest* GetImage(const char* aUrl,
nsIImageRequestObserver *aObserver,
nscolor aBackgroundColor,
PRUint32 aWidth, PRUint32 aHeight,
PRUint32 aFlags) = 0;
/**
* Halt decoding of images or animation without destroying associated
* pixmap data. All ImageRequests created with this ImageGroup
* are interrupted.
*/
virtual void Interrupt(void) = 0;
};
/// Factory method for creating an image group
extern NS_GFX nsresult
NS_NewImageGroup(nsIImageGroup **aInstancePtrResult);
#endif

View File

@@ -0,0 +1,83 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsIImageManager_h___
#define nsIImageManager_h___
#include <stdio.h>
#include "nsISupports.h"
#include "nscore.h"
typedef enum
{
nsImageType_kUnknown = 0,
nsImageType_kGIF = 1,
nsImageType_kXBM = 2,
nsImageType_kJPEG = 3,
nsImageType_kPPM = 4,
nsImageType_kPNG = 5
} nsImageType;
// IID for the nsIImageManager interface
#define NS_IIMAGEMANAGER_IID \
{ 0x9f327100, 0xad5a, 0x11d1, \
{ 0x9b, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
/**
*
* Image manager. There is only a single instance, returned when invoking
* the factory instantiation method. A user of the image library should
* hold on to the singleton image manager.
*/
class nsIImageManager : public nsISupports
{
public:
/// Initialization method to be called before use
virtual nsresult Init() = 0;
/// Set the size (in bytes) image cache maintained by the image manager
virtual void SetCacheSize(PRInt32 aCacheSize) = 0;
/// @return the current size of the image cache (in bytes)
virtual PRInt32 GetCacheSize(void) = 0;
/**
* Attempts to release some memory by freeing an image from the image
* cache. This may not always be possible either because all images
* in the cache are in use or because the cache is empty.
*
* @return the new approximate size of the imagelib cache.
*/
virtual PRInt32 ShrinkCache(void) = 0;
/**
* Determine the type of the image, based on the first few bytes of data.
*
* @param buf - a buffer of image data
* @param length - the length of the buffer
*
* @return the type of the image, if known
*/
virtual nsImageType GetImageType(const char *buf, PRInt32 length) = 0;
};
/// Factory method to get a reference to the singleton image manager
extern NS_GFX nsresult
NS_NewImageManager(nsIImageManager **aInstancePtrResult);
#endif

View File

@@ -0,0 +1,167 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsIImageObserver_h___
#define nsIImageObserver_h___
#include <stdio.h>
#include "nsISupports.h"
#include "nscore.h"
class nsIImage;
class nsIImageRequest;
class nsIImageGroup;
/// Image request notifications
typedef enum {
nsImageNotification_kStartURL, // Start of decode/display for URL.
nsImageNotification_kDescription, // Availability of image description.
nsImageNotification_kDimensions, // Availability of image dimensions.
nsImageNotification_kIsTransparent, // This image is transparent.
nsImageNotification_kPixmapUpdate, // Change in a rectangular area of
// pixels.
nsImageNotification_kFrameComplete, // Completion of a frame of an animated
// image.
nsImageNotification_kProgress, // Notification of percentage decoded.
nsImageNotification_kImageComplete, // Completion of image decoding. There
// may be multiple instances of this
// event per URL due to server push,
// client pull or looping GIF animation.
nsImageNotification_kStopURL, // Completion of decode/display for URL.
nsImageNotification_kImageDestroyed,// Finalization of an image request. This
// is an indication to perform any
// observer related cleanup.
nsImageNotification_kAborted, // Image decode was aborted by either
// the network library or Interrupt().
nsImageNotification_kInternalImage, // Internal image icon.
} nsImageNotification;
/// Image group notifications
typedef enum {
// Start of image loading. Sent when a loading image is
// added to an image group which currently has no loading images.
nsImageGroupNotification_kStartedLoading,
// Some images were aborted. A finished loading message will not be sent
// until the aborted images have been destroyed.
nsImageGroupNotification_kAbortedLoading,
// End of image loading. Sent when the last of the images currently
// in the image group has finished loading.
nsImageGroupNotification_kFinishedLoading,
// Start of image looping. Sent when an animated image starts looping in
// an image group which currently has no looping animations.
nsImageGroupNotification_kStartedLooping,
// End of image looping. Sent when the last of the images currently in
// the image group has finished looping.
nsImageGroupNotification_kFinishedLooping
} nsImageGroupNotification;
/// Image loading errors
typedef enum {
nsImageError_kNotInCache, // Image URL not available in cache when
// kOnlyFromCache flag was set.
nsImageError_kNoData, // Network library unable to fetch
// provided URL.
nsImageError_kImageDataCorrupt, // Checksum error of some kind in
// image data.
nsImageError_kImageDataTruncated, // Missing data at end of stream.
nsImageError_kImageDataIllegal, // Generic image data error.
nsImageError_kInternalError // Internal Image Library error.
} nsImageError;
// IID for the nsIImageRequestObserver interface
#define NS_IIMAGEREQUESTOBSERVER_IID \
{ 0x965467a0, 0xb8f4, 0x11d1, \
{ 0x9b, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
// IID for the nsIImageGroupObserver interface
#define NS_IIMAGEGROUPOBSERVER_IID \
{ 0xb3cad300, 0xb8f4, 0x11d1, \
{ 0x9b, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
/**
* Image request observer interface. The implementor will be notified
* of significant loading events or loading errors.
*/
class nsIImageRequestObserver : public nsISupports {
public:
/**
* Notify the observer of some significant image event. The parameter
* values depend on the notification type as specified below.
*
* kDescription - aParam3 is a string containing the human readable
* description of an image, e.g. "GIF89a 320 x 240 pixels".
* The string storage is static, so it must be copied if
* it is to be preserved after the call to the observer.
* kDimensions - aParam1 and aParam2 are the width and height respectively
* of the image.
* kPixmapUpdate - aParame3 is a pointer to a nsRect struct containing the
* rectangular area of pixels which has been modified by
* the image library. This notification enables the
* client to drive the progressive display of the image.
* kProgress - aParam1 represents the estimated percentage decoded. This
* notification occurs at unspecified intervals. Provided
* that decoding proceeds without error, it is guaranteed that
* notification will take place on completion with a
* percent_progress value of 100.
*
* @param aImageRequest - the image request in question
* @param aImage - the corresponding image object
* @param aNotificationType - the type of notification
* @param aParam1, aParam2, aParam3 - additional information as described
* above.
*/
virtual void Notify(nsIImageRequest *aImageRequest,
nsIImage *aImage,
nsImageNotification aNotificationType,
PRInt32 aParam1, PRInt32 aParam2,
void *aParam3)=0;
/**
* Notify the observer of an error during image loading.
*
* @param aImageRequest - the image request in question
* @param aErrorType - the error code
*/
virtual void NotifyError(nsIImageRequest *aImageRequest,
nsImageError aErrorType)=0;
};
/**
* Image group observer interface. The implementor will be notified
* of significant image group events.
*/
class nsIImageGroupObserver : public nsISupports {
public:
/**
* Notify the observer of some significant image group event.
*
* @param aImageGroup - the image group in question
* @param aNotificationType - the notification code
*/
virtual void Notify(nsIImageGroup *aImageGroup,
nsImageGroupNotification aNotificationType)=0;
};
#endif

View File

@@ -0,0 +1,73 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsIImageRequest_h___
#define nsIImageRequest_h___
#include <stdio.h>
#include "nsISupports.h"
#include "nscore.h"
class nsIImageRequestObserver;
class nsIImage;
// IID for the nsIImageRequest interface
#define NS_IIMAGEREQUEST_IID \
{ 0xc31444c0, 0xaec9, 0x11d1, \
{ 0x9b, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
/**
*
* An image request generated as a result of invoking the
* <code>GetImage</code> method of the <code>nsIImageGroup</code>
* interface.
*/
class nsIImageRequest : public nsISupports {
public:
/// @return the image object associated with the request.
virtual nsIImage* GetImage() = 0;
/**
* Returns the natural dimensions of the image. Returns 0,0
* if the dimensions are unknown.
*
* @param aWidth, aHeight - pointers to integers to be filled in with
* the dimensions.
*/
virtual void GetNaturalDimensions(PRUint32 *aWidth, PRUint32 *aHeight) = 0;
/**
* Add an observers to be informed of image loading notifications.
*
* @param aObserver - An observer to add to the observer list.
* @param boolean indicating whether addition was successful.
*/
virtual PRBool AddObserver(nsIImageRequestObserver *aObserver) = 0;
/**
* Remove a previously added observer from the observer list.
*
* @param aObserver - An observer to remove from the observer list.
* @param boolean indicating whether the removal was successful.
*/
virtual PRBool RemoveObserver(nsIImageRequestObserver *aObserver) = 0;
/// Interrupt loading of just this image.
virtual void Interrupt() = 0;
};
#endif

View File

@@ -0,0 +1,378 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsIRenderingContext_h___
#define nsIRenderingContext_h___
#include "nscore.h"
#include "nsISupports.h"
#include "nsColor.h"
#include "nsCoord.h"
class nsIWidget;
class nsIFontMetrics;
class nsIImage;
class nsTransform2D;
class nsString;
class nsIFontCache;
class nsIDeviceContext;
struct nsFont;
struct nsPoint;
struct nsRect;
// IID for the nsIRenderingContext interface
#define NS_IRENDERING_CONTEXT_IID \
{ 0x7fd8c0f0, 0xa265, 0x11d1, \
{ 0xa8, 0x24, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }
//----------------------------------------------------------------------
//a cross platform way of specifying a navite rendering context
typedef void * nsDrawingSurface;
// RenderingContext interface
class nsIRenderingContext : public nsISupports
{
public:
//TBD: bind/unbind, transformation of scalars (hacky),
//potential drawmode for selection, polygons. MMP
/**
* Initialize the RenderingContext
* @param aContext the device context to use.
* @param aWidget the widget to hook up to
* @result The result of the initialization, NS_Ok if no errors
*/
virtual nsresult Init(nsIDeviceContext* aContext,nsIWidget *aWidget) = 0;
/**
* Initialize the RenderingContext
* @param aContext the device context to use for the drawing.
* @param aSurface the surface to draw into
* @result The result of the initialization, NS_Ok if no errors
*/
virtual nsresult Init(nsIDeviceContext* aContext,nsDrawingSurface aSurface) = 0;
/**
* Reset the rendering context
*/
virtual void Reset() = 0;
/**
* Get the DeviceContext that this RenderingContext was initialized with
* @result the device context
*/
virtual nsIDeviceContext * GetDeviceContext(void) = 0;
/**
* Selects an offscreen drawing surface into the RenderingContext to draw to.
* @param aSurface is the offscreen surface we are going to draw to.
*/
virtual nsresult SelectOffScreenDrawingSurface(nsDrawingSurface aSurface) = 0;
/**
* Save a graphical state onto a stack.
*/
virtual void PushState() = 0;
/**
* Get and and set RenderingContext to this graphical state
*/
virtual void PopState() = 0;
/**
* Tells if a given rectangle is visible within the rendering context
* @param aRect is the rectangle that will be checked for visiblity
* @result If true, that rectanglular area is visable.
*/
virtual PRBool IsVisibleRect(const nsRect& aRect) = 0;
/**
* Sets the clipping for the RenderingContext to the passed in rectangle
* @param aRect The rectangle to set the clipping rectangle to
* @param aIntersect A boolean, if true will cause aRect to be intersected with exsiting clip rects
*/
virtual void SetClipRect(const nsRect& aRect, PRBool aIntersect) = 0;
/**
* Gets the clipping rectangle of the RenderingContext
* @return The clipping rectangle for the RenderingContext
*/
virtual const nsRect& GetClipRect() = 0;
/**
* Sets the forground color for the RenderingContext
* @param aColor The color to set the RenderingContext to
*/
virtual void SetColor(nscolor aColor) = 0;
/**
* Get the forground color for the RenderingContext
* @return The current forground color of the RenderingContext
*/
virtual nscolor GetColor() const = 0;
/**
* Sets the font for the RenderingContext
* @param aFont The font to use in the RenderingContext
*/
virtual void SetFont(const nsFont& aFont) = 0;
/**
* Get the current font for the RenderingContext
* @return The current font of the RenderingContext
*/
virtual const nsFont& GetFont() = 0;
/**
* Get the current fontmetrics for the RenderingContext
* @return The current font of the RenderingContext
*/
virtual nsIFontMetrics* GetFontMetrics() = 0;
/**
* Add in a translate to the RenderingContext's transformation matrix
* @param aX The horizontal translation
* @param aY The vertical translation
*/
virtual void Translate(nscoord aX, nscoord aY) = 0;
/**
* Add in a scale to the RenderingContext's transformation matrix
* @param aX The horizontal scale
* @param aY The vertical scale
*/
virtual void Scale(float aSx, float aSy) = 0;
/**
* Get the current transformation matrix for the RenderingContext
* @return The transformation matrix for the RenderingContext
*/
virtual nsTransform2D * GetCurrentTransform() = 0;
/**
* Create an offscreen drawing surface compatible with this RenderingContext
* @param aBounds A rectangle representing the size for the drawing surface.
* if nsnull then a bitmap will not be created and associated
* with the new drawing surface
* @return A nsDrawingSurface
*/
virtual nsDrawingSurface CreateDrawingSurface(nsRect *aBounds) = 0;
/**
* Destroy a drawing surface created by CreateDrawingSurface()
* @param aDS A drawing surface to destroy
*/
virtual void DestroyDrawingSurface(nsDrawingSurface aDS) = 0;
/**
* Draw a line
* @param aXO starting horiztonal coord in twips
* @param aY0 starting vertical coord in twips
* @param aX1 end horiztonal coord in twips
* @param aY1 end vertical coord in twips
*/
virtual void DrawLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1) = 0;
/**
* Draw a rectangle
* @param aRect The rectangle to draw
*/
virtual void DrawRect(const nsRect& aRect) = 0;
/**
* Draw a rectangle
* @param aX Horizontal left Coordinate in twips
* @param aY Vertical top Coordinate in twips
* @param aWidth Width of rectangle in twips
* @param aHeight Height of rectangle in twips
*/
virtual void DrawRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight) = 0;
/**
* Fill a rectangle in the current foreground color
* @param aRect The rectangle to draw
*/
virtual void FillRect(const nsRect& aRect) = 0;
/**
* Fill a rectangle in the current foreground color
* @param aX Horizontal left Coordinate in twips
* @param aY Vertical top Coordinate in twips
* @param aWidth Width of rectangle in twips
* @param aHeight Height of rectangle in twips
*/
virtual void FillRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight) = 0;
/**
* Draw a poly in the current foreground color
* @param aPoints points to use for the drawing, last must equal first
* @param aNumPonts number of points in the polygon
*/
virtual void DrawPolygon(nsPoint aPoints[], PRInt32 aNumPoints) = 0;
/**
* Fill a poly in the current foreground color
* @param aPoints points to use for the drawing, last must equal first
* @param aNumPonts number of points in the polygon
*/
virtual void FillPolygon(nsPoint aPoints[], PRInt32 aNumPoints) = 0;
/**
* Draw an ellipse in the current foreground color
* @param aRect The rectangle define bounds of ellipse to draw
*/
virtual void DrawEllipse(const nsRect& aRect) = 0;
/**
* Draw an ellipse in the current foreground color
* @param aX Horizontal left Coordinate in twips
* @param aY Vertical top Coordinate in twips
* @param aWidth Width of horizontal axis in twips
* @param aHeight Height of vertical axis in twips
*/
virtual void DrawEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight) = 0;
/**
* Fill an ellipse in the current foreground color
* @param aRect The rectangle define bounds of ellipse to draw
*/
virtual void FillEllipse(const nsRect& aRect) = 0;
/**
* Fill an ellipse in the current foreground color
* @param aX Horizontal left Coordinate in twips
* @param aY Vertical top Coordinate in twips
* @param aWidth Width of horizontal axis in twips
* @param aHeight Height of vertical axis in twips
*/
virtual void FillEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight) = 0;
/**
* Draw an arc in the current forground color
* @param aRect The rectangle define bounds of ellipse to use
* @param aStartAngle the starting angle of the arc, in the ellipse
* @param aEndAngle The ending angle of the arc, in the ellipse
*/
virtual void DrawArc(const nsRect& aRect,
float aStartAngle, float aEndAngle) = 0;
/**
* Draw an arc in the current forground color
* @param aX Horizontal left Coordinate in twips
* @param aY Vertical top Coordinate in twips
* @param aWidth Width of horizontal axis in twips
* @param aHeight Height of vertical axis in twips
* @param aStartAngle the starting angle of the arc, in the ellipse
* @param aEndAngle The ending angle of the arc, in the ellipse
*/
virtual void DrawArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
float aStartAngle, float aEndAngle) = 0;
/**
* Fill an arc in the current forground color
* @param aRect The rectangle define bounds of ellipse to use
* @param aStartAngle the starting angle of the arc, in the ellipse
* @param aEndAngle The ending angle of the arc, in the ellipse
*/
virtual void FillArc(const nsRect& aRect,
float aStartAngle, float aEndAngle) = 0;
/**
* Fill an arc in the current forground color
* @param aX Horizontal left Coordinate in twips
* @param aY Vertical top Coordinate in twips
* @param aWidth Width of horizontal axis in twips
* @param aHeight Height of vertical axis in twips
* @param aStartAngle the starting angle of the arc, in the ellipse
* @param aEndAngle The ending angle of the arc, in the ellipse
*/
virtual void FillArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
float aStartAngle, float aEndAngle) = 0;
/**
* Draw a string in the RenderingContext
* @param aString The string to draw
* @param aLength The length of the aString
* @param aX Horizontal starting point of baseline
* @param aY Vertical starting point of baseline.
* @param aWidth Width of the underline
*/
virtual void DrawString(const char *aString, PRUint32 aLength,
nscoord aX, nscoord aY,
nscoord aWidth) = 0;
/**
* Draw a string in the RenderingContext
* @param aString A PRUnichar of the string
* @param aLength The length of the aString
* @param aX Horizontal starting point of baseline
* @param aY Vertical starting point of baseline.
* @param aWidth length in twips of the underline
*/
virtual void DrawString(const PRUnichar *aString, PRUint32 aLength,
nscoord aX, nscoord aY,
nscoord aWidth) = 0;
/**
* Draw a string in the RenderingContext
* @param aString A nsString of the string
* @param aX Horizontal starting point of baseline
* @param aY Vertical starting point of baseline.
* @param aWidth Width of the underline
*/
virtual void DrawString(const nsString& aString, nscoord aX, nscoord aY,
nscoord aWidth) = 0;
/**
* Copy an image to the RenderingContext
* @param aX Horzontal left destination coordinate
* @param aY Vertical top of destinatio coordinate
*/
virtual void DrawImage(nsIImage *aImage, nscoord aX, nscoord aY) = 0;
/**
* Copy an image to the RenderingContext, scaling can occur if width/hieght does not match source
* @param aX Horzontal left destination coordinate
* @param aY Vertical top of destinatio coordinate
* @param aWidth Width of destination,
* @param aHeight Height of destination
*/
virtual void DrawImage(nsIImage *aImage, nscoord aX, nscoord aY,
nscoord aWidth, nscoord aHeight) = 0;
/**
* Copy an image to the RenderingContext, scaling can occur if source/dest rects differ
* @param aRect Destination rectangle to copy the image to
*/
virtual void DrawImage(nsIImage *aImage, const nsRect& aRect) = 0;
/**
* Copy an image to the RenderingContext, scaling/clipping can occur if source/dest rects differ
* @param aSRect Source rectangle to copy from
* @param aDRect Destination rectangle to copy the image to
*/
virtual void DrawImage(nsIImage *aImage, const nsRect& aSRect, const nsRect& aDRect)=0;
/**
* Copy offscreen pixelmap to this RenderingContext
* @param aBounds Destination rectangle to copy to
*/
virtual nsresult CopyOffScreenBits(nsRect &aBounds) = 0;
};
//modifiers for text rendering
#define NS_DRAWSTRING_NORMAL 0x0
#define NS_DRAWSTRING_UNDERLINE 0x1
#define NS_DRAWSTRING_OVERLINE 0x2
#define NS_DRAWSTRING_LINE_THROUGH 0x4
#endif /* nsIRenderingContext_h___ */

87
mozilla/gfx/src/nsImage.h Normal file
View File

@@ -0,0 +1,87 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsImage_h___
#define nsImage_h___
#include "nsIImage.h"
class nsImage : public nsIImage
{
public:
private:
PRInt8 mNumBytesColor; // number of bytes per color
PRInt16 mNumPalleteColors; // either 8 or 0
PRInt32 mSizeImage; // number of bits, not BITYMAPINFOHEADER
PRInt32 mRowBytes; // number of bytes per row
PRUint8 *mColorTable; // color table for the bitmap
LPBYTE mImageBits; // starting address of DIB bits
LPBYTE mAlphaBits; // alpha layer if we made one
PRBool mIsOptimized; // Have we turned our DIB into a GDI?
nsColorMap *mColorMap; // Redundant with mColorTable, but necessary
// for Set/GetColorMap
#ifdef XP_PC
HPALETTE mHPalette;
HBITMAP mHBitmap; // the GDI bitmap
LPBITMAPINFOHEADER mBHead; // BITMAPINFOHEADER
#endif
public:
nsImage();
~nsImage();
#ifdef XP_PC
virtual BOOL Draw(void *aDrawPort,PRInt32 aX,PRInt32 aY,PRInt32 aWidth,PRInt32 aHeight); // until we implement CreateDibSection
virtual PRInt32 GetHeight() { return mBHead->biHeight;}
int GetSizeHeader(){return sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD) * mNumPalleteColors;}
virtual PRInt32 GetWidth() { return mBHead->biWidth;}
BOOL SetSystemPalette(HDC* aHdc);
UINT UsePalette(HDC* aHdc, BOOL bBackground = FALSE);
#endif
void CleanUp();
virtual PRUint8* GetAlphaBits(){return mAlphaBits;}
virtual PRInt32 GetAlphaLineStride() {return mBHead->biWidth;}
virtual PRUint8* GetBits() {return mImageBits;}
virtual PRInt32 GetLineStride() {return mRowBytes;}
int GetSizeImage() {return mSizeImage;}
virtual void Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth,nsMaskRequirements aMaskRequirements);
virtual PRBool IsOptimized() { return mIsOptimized;}
BOOL MakePalette();
virtual nsresult Optimize(void *aDrawPort);
void TestFillBits();
// methods not complete
virtual nsColorMap* GetColorMap();
virtual void ImageUpdated(PRUint8 aFlags, nsRect *aUpdateRect);
NS_DECL_ISUPPORTS
private:
#ifdef XP_PC
void ComputePaletteSize(int aBitCount);
void ComputeMetrics();
#endif
};
#endif

View File

@@ -0,0 +1,293 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsIImageGroup.h"
#include "nsIImageManager.h"
#include "nsIImageObserver.h"
#include "nsIImageRequest.h"
#include "nsImageRequest.h"
#include "ilIImageRenderer.h"
#include "nsImageNet.h"
#include "nsVoidArray.h"
#include "nsIRenderingContext.h"
#include "nsCRT.h"
#include "libimg.h"
#include "il_util.h"
static NS_DEFINE_IID(kIImageGroupIID, NS_IIMAGEGROUP_IID);
static void ns_observer_proc (XP_Observable aSource,
XP_ObservableMsg aMsg,
void* aMsgData,
void* aClosure);
class ImageGroupImpl : public nsIImageGroup
{
public:
ImageGroupImpl(nsIImageManager *aManager);
~ImageGroupImpl();
nsresult Init(nsIRenderingContext *aRenderingContext);
void* operator new(size_t sz) {
void* rv = new char[sz];
nsCRT::zero(rv, sz);
return rv;
}
NS_DECL_ISUPPORTS
virtual PRBool AddObserver(nsIImageGroupObserver *aObserver);
virtual PRBool RemoveObserver(nsIImageGroupObserver *aObserver);
virtual nsIImageRequest* GetImage(const char* aUrl,
nsIImageRequestObserver *aObserver,
nscolor aBackgroundColor,
PRUint32 aWidth, PRUint32 aHeight,
PRUint32 aFlags);
virtual void Interrupt(void);
IL_GroupContext *GetGroupContext() { return mGroupContext; }
nsVoidArray *GetObservers() { return mObservers; }
private:
nsIImageManager *mManager;
IL_GroupContext *mGroupContext;
nsVoidArray *mObservers;
nsIRenderingContext *mRenderingContext;
IL_ColorSpace *mColorSpace;
};
ImageGroupImpl::ImageGroupImpl(nsIImageManager *aManager)
{
NS_INIT_REFCNT();
mManager = aManager;
}
ImageGroupImpl::~ImageGroupImpl()
{
if (mRenderingContext != nsnull) {
NS_RELEASE(mRenderingContext);
}
if (mObservers != nsnull) {
PRInt32 i, count = mObservers->Count();
nsIImageGroupObserver *observer;
for (i = 0; i < count; i++) {
observer = (nsIImageGroupObserver *)mObservers->ElementAt(i);
if (observer != nsnull) {
NS_RELEASE(observer);
}
}
delete mObservers;
}
if (mGroupContext != nsnull) {
IL_DestroyGroupContext(mGroupContext);
}
if (mColorSpace != nsnull) {
IL_ReleaseColorSpace(mColorSpace);
}
if (mManager != nsnull) {
NS_RELEASE(mManager);
}
}
NS_IMPL_ISUPPORTS(ImageGroupImpl, kIImageGroupIID)
nsresult
ImageGroupImpl::Init(nsIRenderingContext *aRenderingContext)
{
ilIImageRenderer *renderer;
nsresult result;
if ((result = NS_NewImageRenderer(&renderer)) != NS_OK) {
return result;
}
// XXX Need to create an image renderer
mGroupContext = IL_NewGroupContext((void *)aRenderingContext,
renderer);
if (mGroupContext == nsnull) {
return NS_ERROR_OUT_OF_MEMORY;
}
mRenderingContext = aRenderingContext;
NS_ADDREF(mRenderingContext);
// XXX Hard coded to be 24-bit. We need to get the right information
// from the rendering context (or device context).
IL_RGBBits colorRGBBits;
colorRGBBits.red_shift = 16;
colorRGBBits.red_bits = 8;
colorRGBBits.green_shift = 8;
colorRGBBits.green_bits = 8;
colorRGBBits.blue_shift = 0;
colorRGBBits.blue_bits = 8;
mColorSpace = IL_CreateTrueColorSpace(&colorRGBBits, 24);
IL_AddRefToColorSpace(mColorSpace);
IL_DisplayData displayData;
displayData.dither_mode = IL_Auto;
displayData.color_space = mColorSpace;
displayData.progressive_display = PR_TRUE;
IL_SetDisplayMode(mGroupContext,
IL_COLOR_SPACE | IL_PROGRESSIVE_DISPLAY | IL_DITHER_MODE,
&displayData);
return NS_OK;
}
PRBool
ImageGroupImpl::AddObserver(nsIImageGroupObserver *aObserver)
{
if (aObserver == nsnull) {
return PR_FALSE;
}
if (mObservers == nsnull) {
mObservers = new nsVoidArray();
if (mObservers == nsnull) {
return PR_FALSE;
}
IL_AddGroupObserver(mGroupContext, ns_observer_proc, (void *)this);
}
NS_ADDREF(aObserver);
mObservers->AppendElement((void *)aObserver);
return PR_TRUE;
}
PRBool
ImageGroupImpl::RemoveObserver(nsIImageGroupObserver *aObserver)
{
PRBool ret;
if (aObserver == nsnull || mObservers == nsnull) {
return PR_FALSE;
}
ret = mObservers->RemoveElement((void *)aObserver);
if (ret == PR_TRUE) {
NS_RELEASE(aObserver);
}
return ret;
}
nsIImageRequest*
ImageGroupImpl::GetImage(const char* aUrl,
nsIImageRequestObserver *aObserver,
nscolor aBackgroundColor,
PRUint32 aWidth, PRUint32 aHeight,
PRUint32 aFlags)
{
NS_PRECONDITION(nsnull != aUrl, "null URL");
ImageRequestImpl *image_req = new ImageRequestImpl();
if (image_req != nsnull) {
if (image_req->Init(mGroupContext, aUrl, aObserver, aBackgroundColor,
aWidth, aHeight, aFlags) == NS_OK) {
NS_ADDREF(image_req);
}
else {
delete image_req;
image_req = nsnull;
}
}
return image_req;
}
void
ImageGroupImpl::Interrupt(void)
{
if (mGroupContext != nsnull) {
IL_InterruptContext(mGroupContext);
}
}
nsresult
NS_NewImageGroup(nsIImageGroup **aInstancePtrResult)
{
nsresult result;
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
nsIImageManager *manager;
if ((result = NS_NewImageManager(&manager)) != NS_OK) {
return result;
}
nsIImageGroup *group = new ImageGroupImpl(manager);
if (group == nsnull) {
return NS_ERROR_OUT_OF_MEMORY;
}
return group->QueryInterface(kIImageGroupIID, (void **) aInstancePtrResult);
}
static void ns_observer_proc (XP_Observable aSource,
XP_ObservableMsg aMsg,
void* aMsgData,
void* aClosure)
{
ImageGroupImpl *image_group = (ImageGroupImpl *)aClosure;
nsVoidArray *observer_list = image_group->GetObservers();
if (observer_list != nsnull) {
PRInt32 i, count = observer_list->Count();
nsIImageGroupObserver *observer;
for (i = 0; i < count; i++) {
observer = (nsIImageGroupObserver *)observer_list->ElementAt(i);
if (observer != nsnull) {
switch (aMsg) {
case IL_STARTED_LOADING:
observer->Notify(image_group,
nsImageGroupNotification_kStartedLoading);
break;
case IL_ABORTED_LOADING:
observer->Notify(image_group,
nsImageGroupNotification_kAbortedLoading);
case IL_FINISHED_LOADING:
observer->Notify(image_group,
nsImageGroupNotification_kFinishedLoading);
case IL_STARTED_LOOPING:
observer->Notify(image_group,
nsImageGroupNotification_kStartedLooping);
case IL_FINISHED_LOOPING:
observer->Notify(image_group,
nsImageGroupNotification_kFinishedLooping);
}
}
}
}
}

View File

@@ -0,0 +1,136 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsIImageManager.h"
#include "libimg.h"
#include "il_strm.h"
#include "nsCRT.h"
#include "nsImageNet.h"
static NS_DEFINE_IID(kIImageManagerIID, NS_IIMAGEMANAGER_IID);
class ImageManagerImpl : public nsIImageManager {
public:
static ImageManagerImpl *sTheImageManager;
ImageManagerImpl();
~ImageManagerImpl();
nsresult Init();
void* operator new(size_t sz) {
void* rv = new char[sz];
nsCRT::zero(rv, sz);
return rv;
}
NS_DECL_ISUPPORTS
virtual void SetCacheSize(PRInt32 aCacheSize);
virtual PRInt32 GetCacheSize(void);
virtual PRInt32 ShrinkCache(void);
virtual nsImageType GetImageType(const char *buf, PRInt32 length);
private:
ilISystemServices *mSS;
};
ImageManagerImpl* ImageManagerImpl::sTheImageManager = nsnull;
ImageManagerImpl::ImageManagerImpl()
{
NS_NewImageSystemServices(&mSS);
NS_ADDREF(mSS);
IL_Init(mSS);
}
ImageManagerImpl::~ImageManagerImpl()
{
IL_Shutdown();
NS_RELEASE(mSS);
}
NS_IMPL_ISUPPORTS(ImageManagerImpl, kIImageManagerIID)
nsresult
ImageManagerImpl::Init()
{
return NS_OK;
}
void
ImageManagerImpl::SetCacheSize(PRInt32 aCacheSize)
{
IL_SetCacheSize(aCacheSize);
}
PRInt32
ImageManagerImpl::GetCacheSize()
{
return IL_GetCacheSize();
}
PRInt32
ImageManagerImpl::ShrinkCache(void)
{
return IL_ShrinkCache();
}
nsImageType
ImageManagerImpl::GetImageType(const char *buf, PRInt32 length)
{
int ret;
NS_PRECONDITION(nsnull != buf, "null ptr");
ret = IL_Type(buf, length);
switch(ret) {
case(IL_GIF):
return nsImageType_kGIF;
case(IL_XBM):
return nsImageType_kXBM;
case(IL_JPEG):
return nsImageType_kJPEG;
case(IL_PPM):
return nsImageType_kPPM;
case(IL_PNG):
return nsImageType_kPNG;
default:
return nsImageType_kUnknown;
}
}
NS_GFX nsresult
NS_NewImageManager(nsIImageManager **aInstancePtrResult)
{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
if (ImageManagerImpl::sTheImageManager == nsnull) {
ImageManagerImpl::sTheImageManager = new ImageManagerImpl();
}
if (ImageManagerImpl::sTheImageManager == nsnull) {
return NS_ERROR_OUT_OF_MEMORY;
}
return ImageManagerImpl::sTheImageManager->QueryInterface(kIImageManagerIID,
(void **) aInstancePtrResult);
}

View File

@@ -0,0 +1,31 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "ilINetContext.h"
#include "ilIURL.h"
#include "ilIImageRenderer.h"
#include "ilISystemServices.h"
#include "nscore.h"
extern NS_GFX nsresult NS_NewImageNetContext(ilINetContext **aInstancePtrResult);
extern NS_GFX nsresult NS_NewImageURL(ilIURL **aInstancePtrResult,
const char *aURL);
extern NS_GFX nsresult NS_NewImageRenderer(ilIImageRenderer **aInstancePtrResult);
extern NS_GFX nsresult NS_NewImageSystemServices(ilISystemServices **aInstancePtrResult);

View File

@@ -0,0 +1,350 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "libimg.h"
#include "nsImageNet.h"
#include "ilINetContext.h"
#include "ilIURL.h"
#include "ilINetReader.h"
#include "nsIInputStream.h"
#include "nsIURL.h"
#include "nsITimer.h"
#include "nsVoidArray.h"
#include "prmem.h"
#include "plstr.h"
#include "il_strm.h"
static NS_DEFINE_IID(kIImageNetContextIID, IL_INETCONTEXT_IID);
static NS_DEFINE_IID(kIURLIID, NS_IURL_IID);
class ImageNetContextImpl : public ilINetContext {
public:
ImageNetContextImpl(NET_ReloadMethod aReloadPolicy);
~ImageNetContextImpl();
NS_DECL_ISUPPORTS
virtual ilINetContext* Clone();
virtual NET_ReloadMethod GetReloadPolicy();
virtual void AddReferer(ilIURL *aUrl);
virtual void Interrupt();
virtual ilIURL* CreateURL(const char *aUrl,
NET_ReloadMethod aReloadMethod);
virtual PRBool IsLocalFileURL(char *aAddress);
virtual PRBool IsURLInMemCache(ilIURL *aUrl);
virtual PRBool IsURLInDiskCache(ilIURL *aUrl);
virtual int GetURL (ilIURL * aUrl, NET_ReloadMethod aLoadMethod,
ilINetReader *aReader);
nsITimer *mTimer;
nsVoidArray *mRequests;
NET_ReloadMethod mReloadPolicy;
};
typedef struct {
ilIURL *mURL;
nsIInputStream *mStream;
} NetRequestStr;
ImageNetContextImpl::ImageNetContextImpl(NET_ReloadMethod aReloadPolicy)
{
NS_INIT_REFCNT();
mTimer = nsnull;
mRequests = nsnull;
mReloadPolicy = aReloadPolicy;
}
ImageNetContextImpl::~ImageNetContextImpl()
{
if (mTimer != nsnull) {
mTimer->Cancel();
NS_RELEASE(mTimer);
}
if (mRequests != nsnull) {
int i, count = mRequests->Count();
for (i=0; i < count; i++) {
NetRequestStr *req = (NetRequestStr *)mRequests->ElementAt(i);
if (req->mURL != nsnull) {
NS_RELEASE(req->mURL);
}
if (req->mStream != nsnull) {
NS_RELEASE(req->mStream);
}
PR_DELETE(req);
}
delete mRequests;
}
}
NS_IMPL_ISUPPORTS(ImageNetContextImpl, kIImageNetContextIID)
ilINetContext*
ImageNetContextImpl::Clone()
{
ilINetContext *cx;
if (NS_NewImageNetContext(&cx) == NS_OK) {
return cx;
}
else {
return nsnull;
}
}
NET_ReloadMethod
ImageNetContextImpl::GetReloadPolicy()
{
return mReloadPolicy;
}
void
ImageNetContextImpl::AddReferer(ilIURL *aUrl)
{
}
void
ImageNetContextImpl::Interrupt()
{
}
ilIURL*
ImageNetContextImpl::CreateURL(const char *aURL,
NET_ReloadMethod aReloadMethod)
{
ilIURL *url;
if (NS_NewImageURL(&url, aURL) == NS_OK) {
return url;
}
else {
return nsnull;
}
}
PRBool
ImageNetContextImpl::IsLocalFileURL(char *aAddress)
{
if (PL_strncasecmp(aAddress, "file:", 5) == 0) {
return PR_TRUE;
}
else {
return PR_FALSE;
}
}
PRBool
ImageNetContextImpl::IsURLInMemCache(ilIURL *aUrl)
{
return PR_FALSE;
}
PRBool
ImageNetContextImpl::IsURLInDiskCache(ilIURL *aUrl)
{
return PR_TRUE;
}
#define IMAGE_BUF_SIZE 4096
void
LoadURLs (nsITimer *aTimer, void *aClosure)
{
ImageNetContextImpl *cx = (ImageNetContextImpl *)aClosure;
NS_RELEASE(aTimer);
cx->mTimer = nsnull;
if (cx->mRequests) {
int i, count = cx->mRequests->Count();
char *buffer = (char *)PR_MALLOC(IMAGE_BUF_SIZE);
if (buffer == nsnull) {
return;
}
for (i=0; i < count; i++) {
NetRequestStr *req = (NetRequestStr *)cx->mRequests->ElementAt(i);
ilIURL *ilurl = req->mURL;
PRInt32 status = 0;
PRBool reschedule = PR_FALSE;
if (ilurl != nsnull) {
nsIURL *nsurl;
ilINetReader *reader = ilurl->GetReader();
nsIInputStream *stream = nsnull;
if (req->mStream != nsnull) {
stream = req->mStream;
}
else {
if (reader->StreamCreated(ilurl, IL_UNKNOWN) == PR_TRUE &&
ilurl->QueryInterface(kIURLIID, (void **)&nsurl) == NS_OK) {
PRInt32 ec;
stream = nsurl->Open(&ec);
if (nsnull == stream) {
reader->StreamAbort(-1);
status = -1;
}
}
else {
reader->StreamAbort(-1);
status = -1;
}
}
if (status == 0) {
PRInt32 err = 0, nb;
PRBool first = (PRBool)(req->mStream == nsnull);
do {
if (reader->WriteReady() <= 0) {
req->mStream = stream;
reschedule = PR_TRUE;
break;
}
err = 0;
nb = stream->Read(&err, buffer, 0,
IMAGE_BUF_SIZE);
if (err != 0 && err != NS_INPUTSTREAM_EOF) {
break;
}
if (first == PR_TRUE) {
PRInt32 ilErr;
ilErr = reader->FirstWrite((const unsigned char *)buffer, nb);
first = PR_FALSE;
/*
* If FirstWrite(...) fails then the image type
* cannot be determined and the il_container
* stream functions have not been initialized!
*/
if (ilErr != 0) {
break;
}
}
reader->Write((const unsigned char *)buffer, nb);
} while (err != NS_INPUTSTREAM_EOF);
if (err == NS_INPUTSTREAM_EOF) {
reader->StreamComplete(PR_FALSE);
}
else if (err != 0) {
reader->StreamAbort(-1);
status = -1;
}
}
if (!reschedule) {
if (stream != nsnull) {
NS_RELEASE(stream);
}
req->mStream = nsnull;
reader->NetRequestDone(ilurl, status);
NS_RELEASE(reader);
NS_RELEASE(ilurl);
}
}
}
for (i=count-1; i >= 0; i--) {
NetRequestStr *req = (NetRequestStr *)cx->mRequests->ElementAt(i);
if (req->mStream == nsnull) {
cx->mRequests->RemoveElementAt(i);
PR_DELETE(req);
}
else if (cx->mTimer == nsnull) {
if (NS_NewTimer(&cx->mTimer) == NS_OK) {
cx->mTimer->Init(LoadURLs, (void *)cx, 0);
}
}
}
PR_FREEIF(buffer);
}
}
int
ImageNetContextImpl::GetURL (ilIURL * aURL,
NET_ReloadMethod aLoadMethod,
ilINetReader *aReader)
{
NS_PRECONDITION(nsnull != aURL, "null URL");
NS_PRECONDITION(nsnull != aReader, "null reader");
if (aURL == nsnull || aReader == nsnull) {
return -1;
}
if (mRequests == nsnull) {
mRequests = new nsVoidArray();
if (mRequests == nsnull) {
// XXX Should still call exit function
return -1;
}
}
if (mTimer == nsnull) {
if (NS_NewTimer(&mTimer) != NS_OK) {
// XXX Should still call exit function
return -1;
}
if (mTimer->Init(LoadURLs, (void *)this, 0) != NS_OK) {
// XXX Should still call exit function
return -1;
}
}
aURL->SetReader(aReader);
NetRequestStr *req = PR_NEWZAP(NetRequestStr);
req->mURL = aURL;
NS_ADDREF(aURL);
mRequests->AppendElement((void *)req);
return 0;
}
nsresult
NS_NewImageNetContext(ilINetContext **aInstancePtrResult)
{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
ilINetContext *cx = new ImageNetContextImpl(NET_NORMAL_RELOAD);
if (cx == nsnull) {
return NS_ERROR_OUT_OF_MEMORY;
}
return cx->QueryInterface(kIImageNetContextIID, (void **) aInstancePtrResult);
}

View File

@@ -0,0 +1,282 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "libimg.h"
#include "ilIImageRenderer.h"
#include "nsIImage.h"
#include "nsIRenderingContext.h"
#include "ni_pixmp.h"
#include "il_util.h"
#include "nsGfxCIID.h"
#include "nsIDeviceContext.h"
static NS_DEFINE_IID(kIImageRendererIID, IL_IIMAGERENDERER_IID);
class ImageRendererImpl : public ilIImageRenderer {
public:
static IL_ColorSpace *sPseudoColorSpace;
ImageRendererImpl();
~ImageRendererImpl();
NS_DECL_ISUPPORTS
virtual void NewPixmap(void* aDisplayContext,
PRInt32 aWidth, PRInt32 aHeight,
IL_Pixmap* aImage, IL_Pixmap* aMask);
virtual void UpdatePixmap(void* aDisplayContext,
IL_Pixmap* aImage,
PRInt32 aXOffset, PRInt32 aYOffset,
PRInt32 aWidth, PRInt32 aHeight);
virtual void ControlPixmapBits(void* aDisplayContext,
IL_Pixmap* aImage, PRUint32 aControlMsg);
virtual void DestroyPixmap(void* aDisplayContext, IL_Pixmap* aImage);
virtual void DisplayPixmap(void* aDisplayContext,
IL_Pixmap* aImage, IL_Pixmap* aMask,
PRInt32 aX, PRInt32 aY,
PRInt32 aXOffset, PRInt32 aYOffset,
PRInt32 aWidth, PRInt32 aHeight);
virtual void DisplayIcon(void* aDisplayContext,
PRInt32 aX, PRInt32 aY, PRUint32 aIconNumber);
virtual void GetIconDimensions(void* aDisplayContext,
PRInt32 *aWidthPtr, PRInt32 *aHeightPtr,
PRUint32 aIconNumber);
};
IL_ColorSpace *ImageRendererImpl::sPseudoColorSpace = nsnull;
ImageRendererImpl::ImageRendererImpl()
{
NS_INIT_REFCNT();
}
ImageRendererImpl::~ImageRendererImpl()
{
}
NS_IMPL_ISUPPORTS(ImageRendererImpl, kIImageRendererIID)
void
ImageRendererImpl::NewPixmap(void* aDisplayContext,
PRInt32 aWidth, PRInt32 aHeight,
IL_Pixmap* aImage, IL_Pixmap* aMask)
{
nsIRenderingContext *rc = (nsIRenderingContext *)aDisplayContext;
nsIImage *img;
nsresult rv;
static NS_DEFINE_IID(kImageCID, NS_IMAGE_CID);
static NS_DEFINE_IID(kImageIID, NS_IIMAGE_IID);
rv = NSRepository::CreateInstance(kImageCID, nsnull, kImageIID, (void **)&img);
if (NS_OK != rv)
return;
PRInt32 depth;
if (aImage->header.color_space->pixmap_depth == 8) {
depth = 8;
}
else {
depth = 24;
}
img->Init(aWidth, aHeight, depth,
(aMask == nsnull) ? nsMaskRequirements_kNoMask :
nsMaskRequirements_kNeeds1Bit);
aImage->bits = img->GetBits();
aImage->client_data = img;
NS_ADDREF(img);
aImage->header.width = aWidth;
aImage->header.height = aHeight;
aImage->header.widthBytes = img->GetLineStride();
if (aMask) {
aMask->bits = img->GetAlphaBits();
aMask->client_data = img;
aMask->header.width = aWidth;
aMask->header.height = aHeight;
}
if (aImage->header.color_space->pixmap_depth == 8) {
IL_ColorMap *cmap;
if (sPseudoColorSpace == nsnull) {
cmap = IL_NewCubeColorMap(nsnull, 0, 216);
if (cmap != nsnull) {
sPseudoColorSpace = IL_CreatePseudoColorSpace(cmap, 8, 8);
if (sPseudoColorSpace == nsnull) {
IL_DestroyColorMap(cmap);
// XXX We should do something here
return;
}
}
else {
// XXX We should do something here
return;
}
}
IL_AddRefToColorSpace(sPseudoColorSpace);
IL_ReleaseColorSpace(aImage->header.color_space);
aImage->header.color_space = sPseudoColorSpace;
cmap = &sPseudoColorSpace->cmap;
nsColorMap *nscmap = img->GetColorMap();
PRUint8 *mapptr = nscmap->Index;
int i;
for (i=0; i < cmap->num_colors; i++) {
*mapptr++ = cmap->map[i].red;
*mapptr++ = cmap->map[i].green;
*mapptr++ = cmap->map[i].blue;
}
nsIDeviceContext *dx = rc->GetDeviceContext();
img->ImageUpdated(dx, nsImageUpdateFlags_kColorMapChanged, nsnull);
NS_IF_RELEASE(dx);
if (aImage->header.transparent_pixel) {
PRUint8 red, green, blue;
PRUint8 *lookup_table = (PRUint8 *)aImage->header.color_space->cmap.table;
red = aImage->header.transparent_pixel->red;
green = aImage->header.transparent_pixel->green;
blue = aImage->header.transparent_pixel->blue;
aImage->header.transparent_pixel->index =
lookup_table[((red >> 3) << 10) |
((green >> 3) << 5) |
(blue >> 3)];
}
}
else {
IL_RGBBits colorRGBBits;
IL_ColorSpace *colorSpace;
colorRGBBits.red_shift = 16;
colorRGBBits.red_bits = 8;
colorRGBBits.green_shift = 8;
colorRGBBits.green_bits = 8;
colorRGBBits.blue_shift = 0;
colorRGBBits.blue_bits = 8;
colorSpace = IL_CreateTrueColorSpace(&colorRGBBits, 24);
IL_AddRefToColorSpace(colorSpace);
IL_ReleaseColorSpace(aImage->header.color_space);
aImage->header.color_space = colorSpace;
}
}
void
ImageRendererImpl::UpdatePixmap(void* aDisplayContext,
IL_Pixmap* aImage,
PRInt32 aXOffset, PRInt32 aYOffset,
PRInt32 aWidth, PRInt32 aHeight)
{
nsIRenderingContext *rc = (nsIRenderingContext *)aDisplayContext;
nsIImage *img = (nsIImage *)aImage->client_data;
nsIDeviceContext *dx = rc->GetDeviceContext();
nsRect drect(aXOffset, aYOffset, aWidth, aHeight);
img->ImageUpdated(dx, nsImageUpdateFlags_kBitsChanged, &drect);
NS_IF_RELEASE(dx);
}
void
ImageRendererImpl::ControlPixmapBits(void* aDisplayContext,
IL_Pixmap* aImage, PRUint32 aControlMsg)
{
nsIRenderingContext *rc = (nsIRenderingContext *)aDisplayContext;
nsIImage *img = (nsIImage *)aImage->client_data;
if (aControlMsg == IL_RELEASE_BITS) {
nsIDeviceContext *dx = rc->GetDeviceContext();
if (nsnull != dx) {
nsDrawingSurface surf = dx->GetDrawingSurface(*rc);
if (nsnull != surf)
img->Optimize(surf);
NS_RELEASE(dx);
}
}
}
void
ImageRendererImpl::DestroyPixmap(void* aDisplayContext, IL_Pixmap* aImage)
{
nsIRenderingContext *rc = (nsIRenderingContext *)aDisplayContext;
nsIImage *img = (nsIImage *)aImage->client_data;
aImage->client_data = nsnull;
if (img) {
NS_RELEASE(img);
}
}
void
ImageRendererImpl::DisplayPixmap(void* aDisplayContext,
IL_Pixmap* aImage, IL_Pixmap* aMask,
PRInt32 aX, PRInt32 aY,
PRInt32 aXOffset, PRInt32 aYOffset,
PRInt32 aWidth, PRInt32 aHeight)
{
nsIRenderingContext *rc = (nsIRenderingContext *)aDisplayContext;
nsIImage *img = (nsIImage *)aImage->client_data;
// XXX Need better version of DrawImage
rc->DrawImage(img, aX, aY);
}
void
ImageRendererImpl::DisplayIcon(void* aDisplayContext,
PRInt32 aX, PRInt32 aY, PRUint32 aIconNumber)
{
nsIRenderingContext *rc = (nsIRenderingContext *)aDisplayContext;
}
void
ImageRendererImpl::GetIconDimensions(void* aDisplayContext,
PRInt32 *aWidthPtr, PRInt32 *aHeightPtr,
PRUint32 aIconNumber)
{
nsIRenderingContext *rc = (nsIRenderingContext *)aDisplayContext;
}
nsresult
NS_NewImageRenderer(ilIImageRenderer **aInstancePtrResult)
{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
ilIImageRenderer *renderer = new ImageRendererImpl();
if (renderer == nsnull) {
return NS_ERROR_OUT_OF_MEMORY;
}
return renderer->QueryInterface(kIImageRendererIID,
(void **) aInstancePtrResult);
}

View File

@@ -0,0 +1,326 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsImageRequest.h"
#include "nsIImageGroup.h"
#include "nsIImageObserver.h"
#include "nsIImage.h"
#include "nsVoidArray.h"
#include "nsRect.h"
#include "ilINetContext.h"
#include "nsImageNet.h"
static NS_DEFINE_IID(kIImageRequestIID, NS_IIMAGEREQUEST_IID);
static void ns_observer_proc (XP_Observable aSource,
XP_ObservableMsg aMsg,
void* aMsgData,
void* aClosure);
ImageRequestImpl::ImageRequestImpl()
{
}
ImageRequestImpl::~ImageRequestImpl()
{
// Observer list destroyed by the image library
}
nsresult
ImageRequestImpl::Init(IL_GroupContext *aGroupContext,
const char* aUrl,
nsIImageRequestObserver *aObserver,
nscolor aBackgroundColor,
PRUint32 aWidth, PRUint32 aHeight,
PRUint32 aFlags)
{
NS_PRECONDITION(nsnull != aGroupContext, "null group context");
NS_PRECONDITION(nsnull != aUrl, "null URL");
NS_Error status;
IL_IRGB bgcolor;
PRUint32 flags;
nsresult result;
mGroupContext = aGroupContext;
if (AddObserver(aObserver) == PR_FALSE) {
return NS_ERROR_OUT_OF_MEMORY;
}
status = XP_NewObserverList(NULL, &mXPObserver);
if (status < 0) {
return NS_ERROR_OUT_OF_MEMORY;
}
status = XP_AddObserver(mXPObserver, ns_observer_proc, (void *)this);
if (status < 0) {
XP_DisposeObserverList(mXPObserver);
mXPObserver = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
bgcolor.red = NS_GET_R(aBackgroundColor);
bgcolor.green = NS_GET_G(aBackgroundColor);
bgcolor.blue = NS_GET_B(aBackgroundColor);
flags = ((aFlags & IL_HIGH_PRIORITY) ? nsImageLoadFlags_kHighPriority : 0) |
((aFlags & IL_STICKY) ? nsImageLoadFlags_kSticky : 0) |
((aFlags & IL_BYPASS_CACHE) ? nsImageLoadFlags_kBypassCache : 0) |
((aFlags & IL_ONLY_FROM_CACHE) ? nsImageLoadFlags_kOnlyFromCache : 0);
ilINetContext *net_cx;
if ((result = NS_NewImageNetContext(&net_cx)) != NS_OK) {
XP_DisposeObserverList(mXPObserver);
mXPObserver = nsnull;
return result;
}
mImageReq = IL_GetImage(aUrl, aGroupContext, mXPObserver, &bgcolor,
aWidth, aHeight, flags, (void *)net_cx);
if (mImageReq == nsnull) {
XP_DisposeObserverList(mXPObserver);
mXPObserver = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
NS_IMPL_ADDREF(ImageRequestImpl)
NS_IMPL_QUERY_INTERFACE(ImageRequestImpl, kIImageRequestIID)
nsrefcnt ImageRequestImpl::Release(void)
{
if (--mRefCnt == 0) {
IL_DestroyImage(mImageReq);
delete this;
return 0;
}
return mRefCnt;
}
nsIImage*
ImageRequestImpl::GetImage()
{
if (mImageReq != nsnull) {
IL_Pixmap *pixmap = IL_GetImagePixmap(mImageReq);
if (pixmap != nsnull) {
nsIImage *image = (nsIImage *)pixmap->client_data;
if (image != nsnull) {
NS_ADDREF(image);
return image;
}
}
}
return nsnull;
}
void
ImageRequestImpl::GetNaturalDimensions(PRUint32 *aWidth, PRUint32 *aHeight)
{
if (mImageReq != nsnull) {
IL_GetNaturalDimensions(mImageReq, (int *)aWidth, (int *)aHeight);
}
else {
*aWidth = 0;
*aHeight = 0;
}
}
PRBool
ImageRequestImpl::AddObserver(nsIImageRequestObserver *aObserver)
{
if (aObserver == nsnull) {
return PR_FALSE;
}
if (mObservers == nsnull) {
mObservers = new nsVoidArray();
if (mObservers == nsnull) {
return PR_FALSE;
}
}
NS_ADDREF(aObserver);
mObservers->AppendElement((void *)aObserver);
return PR_TRUE;
}
PRBool
ImageRequestImpl::RemoveObserver(nsIImageRequestObserver *aObserver)
{
PRBool ret;
if (aObserver == nsnull || mObservers == nsnull) {
return PR_FALSE;
}
ret = mObservers->RemoveElement((void *)aObserver);
if (ret == PR_TRUE) {
NS_RELEASE(aObserver);
}
return ret;
}
void
ImageRequestImpl::Interrupt()
{
if (mImageReq != nsnull) {
IL_InterruptRequest(mImageReq);
}
}
static void ns_observer_proc (XP_Observable aSource,
XP_ObservableMsg aMsg,
void* aMsgData,
void* aClosure)
{
ImageRequestImpl *image_request = (ImageRequestImpl *)aClosure;
IL_MessageData *message_data = (IL_MessageData *)aMsgData;
nsVoidArray *observer_list = image_request->GetObservers();
nsIImage *image = nsnull;
// IL_ImageReq *il_image_req = image_request->GetImageRequest();
IL_ImageReq *il_image_req = (IL_ImageReq *)aSource;
if (il_image_req != nsnull) {
IL_Pixmap *pixmap = IL_GetImagePixmap(il_image_req);
if (pixmap != nsnull) {
image = (nsIImage *)pixmap->client_data;
}
}
if (observer_list != nsnull) {
PRInt32 i, count = observer_list->Count();
nsIImageRequestObserver *observer;
for (i = 0; i < count; i++) {
observer = (nsIImageRequestObserver *)observer_list->ElementAt(i);
if (observer != nsnull) {
switch (aMsg) {
case IL_START_URL:
observer->Notify(image_request,
image, nsImageNotification_kStartURL, 0, 0,
nsnull);
break;
case IL_DESCRIPTION:
observer->Notify(image_request,
image, nsImageNotification_kDescription, 0, 0,
message_data->description);
break;
case IL_DIMENSIONS:
observer->Notify(image_request,
image, nsImageNotification_kDimensions,
(PRInt32)message_data->width,
(PRInt32)message_data->height,
nsnull);
break;
case IL_IS_TRANSPARENT:
observer->Notify(image_request,
image, nsImageNotification_kIsTransparent, 0, 0,
nsnull);
break;
case IL_PIXMAP_UPDATE:
{
nsRect rect(message_data->update_rect.x_origin,
message_data->update_rect.y_origin,
message_data->update_rect.width,
message_data->update_rect.height);
observer->Notify(image_request,
image, nsImageNotification_kPixmapUpdate, 0, 0,
&rect);
}
break;
case IL_FRAME_COMPLETE:
observer->Notify(image_request,
image, nsImageNotification_kFrameComplete, 0, 0,
nsnull);
break;
case IL_PROGRESS:
observer->Notify(image_request,
image, nsImageNotification_kProgress,
message_data->percent_progress, 0,
nsnull);
break;
case IL_IMAGE_COMPLETE:
observer->Notify(image_request,
image, nsImageNotification_kImageComplete, 0, 0,
nsnull);
break;
case IL_STOP_URL:
observer->Notify(image_request,
image, nsImageNotification_kStopURL, 0, 0,
nsnull);
break;
case IL_IMAGE_DESTROYED:
image_request->SetImageRequest(nsnull);
observer->Notify(image_request,
image, nsImageNotification_kImageDestroyed, 0, 0,
nsnull);
break;
case IL_ABORTED:
observer->Notify(image_request,
image, nsImageNotification_kAborted, 0, 0,
nsnull);
break;
case IL_INTERNAL_IMAGE:
observer->Notify(image_request,
image, nsImageNotification_kInternalImage, 0, 0,
nsnull);
break;
case IL_NOT_IN_CACHE:
observer->NotifyError(image_request,
nsImageError_kNotInCache);
break;
case IL_ERROR_NO_DATA:
observer->NotifyError(image_request,
nsImageError_kNoData);
break;
case IL_ERROR_IMAGE_DATA_CORRUPT:
observer->NotifyError(image_request,
nsImageError_kImageDataCorrupt);
break;
case IL_ERROR_IMAGE_DATA_TRUNCATED:
observer->NotifyError(image_request,
nsImageError_kImageDataTruncated);
break;
case IL_ERROR_IMAGE_DATA_ILLEGAL:
observer->NotifyError(image_request,
nsImageError_kImageDataIllegal);
break;
case IL_ERROR_INTERNAL:
observer->NotifyError(image_request,
nsImageError_kInternalError);
break;
}
}
}
}
}

View File

@@ -0,0 +1,74 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsImageRequest_h___
#define nsImageRequest_h___
#include "nsIImageRequest.h"
#include "libimg.h"
#include "nsCRT.h"
#include "nsColor.h"
class nsVoidArray;
class nsIImageRequestObserver;
class ImageRequestImpl : public nsIImageRequest {
public:
ImageRequestImpl();
~ImageRequestImpl();
nsresult Init(IL_GroupContext *aGroupContext, const char* aUrl,
nsIImageRequestObserver *aObserver,
nscolor aBackgroundColor,
PRUint32 aWidth, PRUint32 aHeight,
PRUint32 aFlags);
void* operator new(size_t sz) {
void* rv = new char[sz];
nsCRT::zero(rv, sz);
return rv;
}
NS_DECL_ISUPPORTS
// Get the image associated with the request.
virtual nsIImage* GetImage();
// Return the natural dimensions of the image. Returns 0,0
//if the dimensions are unknown.
virtual void GetNaturalDimensions(PRUint32 *aWidth, PRUint32 *aHeight);
// Add and remove observers to listen in on image loading notifications
virtual PRBool AddObserver(nsIImageRequestObserver *aObserver);
virtual PRBool RemoveObserver(nsIImageRequestObserver *aObserver);
// Interrupt loading of just this image.
virtual void Interrupt();
IL_ImageReq *GetImageRequest() { return mImageReq; }
void SetImageRequest(IL_ImageReq *aImageReq) { mImageReq = aImageReq; }
nsVoidArray *GetObservers() { return mObservers; }
private:
IL_ImageReq *mImageReq;
IL_GroupContext *mGroupContext;
nsVoidArray *mObservers;
XP_ObserverList mXPObserver;
};
#endif

View File

@@ -0,0 +1,134 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "ilISystemServices.h"
#include "nsITimer.h"
#include "prtypes.h"
#include "prmem.h"
#include "nsCRT.h"
static NS_DEFINE_IID(kISystemServicesIID, IL_ISYSTEMSERVICES_IID);
class ImageSystemServicesImpl : public ilISystemServices {
public:
static ImageSystemServicesImpl *sSS;
ImageSystemServicesImpl();
~ImageSystemServicesImpl();
void* operator new(size_t sz) {
void* rv = new char[sz];
nsCRT::zero(rv, sz);
return rv;
}
NS_DECL_ISUPPORTS
virtual void * SetTimeout(ilTimeoutCallbackFunction aFunc,
void * aClosure, PRUint32 aMsecs);
virtual void ClearTimeout(void *aTimerID);
};
typedef struct {
ilTimeoutCallbackFunction mFunc;
void *mClosure;
} TimerClosure;
ImageSystemServicesImpl* ImageSystemServicesImpl::sSS = nsnull;
ImageSystemServicesImpl::ImageSystemServicesImpl()
{
}
ImageSystemServicesImpl::~ImageSystemServicesImpl()
{
}
NS_IMPL_ISUPPORTS(ImageSystemServicesImpl, kISystemServicesIID)
void
timer_callback (nsITimer *aTimer, void *aClosure)
{
TimerClosure *tc = (TimerClosure *)aClosure;
(*tc->mFunc)(tc->mClosure);
NS_RELEASE(aTimer);
PR_DELETE(tc);
}
void *
ImageSystemServicesImpl::SetTimeout(ilTimeoutCallbackFunction aFunc,
void * aClosure, PRUint32 aMsecs)
{
nsITimer *timer;
TimerClosure *tc;
if (NS_NewTimer(&timer) != NS_OK) {
return nsnull;
}
tc = (TimerClosure *)PR_NEWZAP(TimerClosure);
if (tc == nsnull) {
NS_RELEASE(timer);
return nsnull;
}
tc->mFunc = aFunc;
tc->mClosure = aClosure;
if (timer->Init(timer_callback, (void *)tc, aMsecs) != NS_OK) {
NS_RELEASE(timer);
PR_DELETE(tc);
return nsnull;
}
NS_ADDREF(timer);
return (void *)timer;
}
void
ImageSystemServicesImpl::ClearTimeout(void *aTimerID)
{
nsITimer *timer = (nsITimer *)aTimerID;
timer->Cancel();
NS_RELEASE(timer);
}
nsresult
NS_NewImageSystemServices(ilISystemServices **aInstancePtrResult)
{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
if (ImageSystemServicesImpl::sSS == nsnull) {
ImageSystemServicesImpl::sSS = new ImageSystemServicesImpl();
}
if (ImageSystemServicesImpl::sSS == nsnull) {
return NS_ERROR_OUT_OF_MEMORY;
}
return ImageSystemServicesImpl::sSS->QueryInterface(kISystemServicesIID,
(void **) aInstancePtrResult);
}

View File

@@ -0,0 +1,179 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "libimg.h"
#include "nsImageNet.h"
#include "ilINetContext.h"
#include "ilINetReader.h"
#include "ilIURL.h"
#include "nsIURL.h"
#include "nsString.h"
#include "il_strm.h"
static NS_DEFINE_IID(kIImageURLIID, IL_IURL_IID);
class ImageURLImpl : public ilIURL {
public:
ImageURLImpl(const char *aURL);
~ImageURLImpl();
NS_DECL_ISUPPORTS
virtual void SetReader(ilINetReader *aReader);
virtual ilINetReader *GetReader();
virtual int GetContentLength();
virtual const char* GetAddress();
virtual time_t GetExpires();
virtual void SetBackgroundLoad(PRBool aBgload);
private:
nsIURL *mURL;
ilINetReader *mReader;
};
ImageURLImpl::ImageURLImpl(const char *aURL)
{
NS_INIT_REFCNT();
NS_NewURL(&mURL, aURL);
mReader = nsnull;
}
ImageURLImpl::~ImageURLImpl()
{
if (mURL != nsnull) {
NS_RELEASE(mURL);
}
if (mReader != nsnull) {
NS_RELEASE(mReader);
}
}
nsresult
ImageURLImpl::QueryInterface(const nsIID& aIID,
void** aInstancePtr)
{
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kClassIID, kIImageURLIID);
static NS_DEFINE_IID(kURLIID, NS_IURL_IID);
if (aIID.Equals(kURLIID)) {
*aInstancePtr = (void*) mURL;
mURL->AddRef();
return NS_OK;
}
if (aIID.Equals(kClassIID)) {
*aInstancePtr = (void*) this;
AddRef();
return NS_OK;
}
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*) ((nsISupports*)this);
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMPL_ADDREF(ImageURLImpl)
nsrefcnt ImageURLImpl::Release(void)
{
if (--mRefCnt == 0) {
delete this;
return 0;
}
return mRefCnt;
}
void
ImageURLImpl::SetReader(ilINetReader *aReader)
{
if (mReader != nsnull) {
NS_RELEASE(mReader);
}
mReader = aReader;
if (mReader != nsnull) {
NS_ADDREF(mReader);
}
}
ilINetReader *
ImageURLImpl::GetReader()
{
if (mReader != nsnull) {
NS_ADDREF(mReader);
}
return mReader;
}
int
ImageURLImpl::GetContentLength()
{
return 0;
}
const char*
ImageURLImpl::GetAddress()
{
if (mURL != nsnull) {
return mURL->GetSpec();
}
else {
return nsnull;
}
}
time_t
ImageURLImpl::GetExpires()
{
return 0x7FFFFFFF;
}
void
ImageURLImpl::SetBackgroundLoad(PRBool aBgload)
{
}
nsresult
NS_NewImageURL(ilIURL **aInstancePtrResult, const char *aURL)
{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr");
if (nsnull == aInstancePtrResult) {
return NS_ERROR_NULL_POINTER;
}
ilIURL *url = new ImageURLImpl(aURL);
if (url == nsnull) {
return NS_ERROR_OUT_OF_MEMORY;
}
return url->QueryInterface(kIImageURLIID, (void **) aInstancePtrResult);
}

View File

@@ -0,0 +1,71 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef NSMARGIN_H
#define NSMARGIN_H
#include "nsCoord.h"
struct nsMargin {
nscoord left, top, right, bottom;
// Constructors
nsMargin() {}
nsMargin(const nsMargin& aMargin) {*this = aMargin;}
nsMargin(nscoord aLeft, nscoord aTop,
nscoord aRight, nscoord aBottom) {left = aLeft; top = aTop;
right = aRight; bottom = aBottom;}
void SizeTo(nscoord aLeft, nscoord aTop,
nscoord aRight, nscoord aBottom) {left = aLeft; top = aTop;
right = aRight; bottom = aBottom;}
void SizeBy(nscoord aLeft, nscoord aTop,
nscoord aRight, nscoord aBottom) {left += aLeft; top += aTop;
right += aRight; bottom += aBottom;}
// Overloaded operators. Note that '=' isn't defined so we'll get the
// compiler generated default assignment operator
PRBool operator==(const nsMargin& aMargin) const {
return (PRBool) ((left == aMargin.left) && (top == aMargin.top) &&
(right == aMargin.right) && (bottom == aMargin.bottom));
}
PRBool operator!=(const nsMargin& aMargin) const {
return (PRBool) ((left != aMargin.left) || (top != aMargin.top) ||
(right != aMargin.right) || (bottom != aMargin.bottom));
}
nsMargin operator+(const nsMargin& aMargin) const {
return nsMargin(left + aMargin.left, top + aMargin.top,
right + aMargin.right, bottom + aMargin.bottom);
}
nsMargin operator-(const nsMargin& aMargin) const {
return nsMargin(left - aMargin.left, top - aMargin.top,
right - aMargin.right, bottom - aMargin.bottom);
}
nsMargin& operator+=(const nsMargin& aMargin) {left += aMargin.left;
top += aMargin.top;
right += aMargin.right;
bottom += aMargin.bottom;
return *this;}
nsMargin& operator-=(const nsMargin& aMargin) {left -= aMargin.left;
top -= aMargin.top;
right -= aMargin.right;
bottom -= aMargin.bottom;
return *this;}
};
#endif /* NSMARGIN_H */

61
mozilla/gfx/src/nsPoint.h Normal file
View File

@@ -0,0 +1,61 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef NSPOINT_H
#define NSPOINT_H
#include "nsCoord.h"
struct nsPoint {
nscoord x, y;
// Constructors
nsPoint() {}
nsPoint(const nsPoint& aPoint) {x = aPoint.x; y = aPoint.y;}
nsPoint(nscoord aX, nscoord aY) {x = aX; y = aY;}
void MoveTo(nscoord aX, nscoord aY) {x = aX; y = aY;}
void MoveBy(nscoord aDx, nscoord aDy) {x += aDx; y += aDy;}
// Overloaded operators. Note that '=' isn't defined so we'll get the
// compiler generated default assignment operator
PRBool operator==(const nsPoint& aPoint) const {
return (PRBool) ((x == aPoint.x) && (y == aPoint.y));
}
PRBool operator!=(const nsPoint& aPoint) const {
return (PRBool) ((x != aPoint.x) || (y != aPoint.y));
}
nsPoint operator+(const nsPoint& aPoint) const {
return nsPoint(x + aPoint.x, y + aPoint.y);
}
nsPoint operator-(const nsPoint& aPoint) const {
return nsPoint(x - aPoint.x, y - aPoint.y);
}
nsPoint& operator+=(const nsPoint& aPoint) {
x += aPoint.x;
y += aPoint.y;
return *this;
}
nsPoint& operator-=(const nsPoint& aPoint) {
x -= aPoint.x;
y -= aPoint.y;
return *this;
}
};
#endif /* NSPOINT_H */

173
mozilla/gfx/src/nsRect.cpp Normal file
View File

@@ -0,0 +1,173 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsRect.h"
#include "nsString.h"
#include "nsUnitConversion.h"
#define MIN(a,b)\
((a) < (b) ? (a) : (b))
#define MAX(a,b)\
((a) > (b) ? (a) : (b))
// Containment
PRBool nsRect::Contains(nscoord aX, nscoord aY) const
{
return (PRBool) ((aX >= x) && (aY >= y) &&
(aX < XMost()) && (aY < YMost()));
}
PRBool nsRect::Contains(const nsRect &aRect) const
{
return (PRBool) ((aRect.x >= x) && (aRect.y >= y) &&
(aRect.XMost() <= XMost()) && (aRect.YMost() <= YMost()));
}
// Intersection. Returns TRUE if the receiver overlaps aRect and
// FALSE otherwise
PRBool nsRect::Intersects(const nsRect &aRect) const
{
return (PRBool) ((x < aRect.XMost()) && (y < aRect.YMost()) &&
(aRect.x < XMost()) && (aRect.y < YMost()));
}
// Computes the area in which aRect1 and aRect2 overlap and fills 'this' with
// the result. Returns FALSE if the rectangles don't intersect.
PRBool nsRect::IntersectRect(const nsRect &aRect1, const nsRect &aRect2)
{
nscoord xmost1 = aRect1.XMost();
nscoord ymost1 = aRect1.YMost();
nscoord xmost2 = aRect2.XMost();
nscoord ymost2 = aRect2.YMost();
nscoord temp;
x = MAX(aRect1.x, aRect2.x);
y = MAX(aRect1.y, aRect2.y);
// Compute the destination width
temp = MIN(xmost1, xmost2);
if (temp <= x) {
Empty();
return PR_FALSE;
}
width = temp - x;
// Compute the destination height
temp = MIN(ymost1, ymost2);
if (temp <= y) {
Empty();
return PR_FALSE;
}
height = temp - y;
return PR_TRUE;
}
// Computes the smallest rectangle that contains both aRect1 and aRect2 and
// fills 'this' with the result. Returns FALSE if both aRect1 and aRect2 are
// empty and TRUE otherwise
PRBool nsRect::UnionRect(const nsRect &aRect1, const nsRect &aRect2)
{
PRBool result = PR_TRUE;
// Is aRect1 empty?
if (aRect1.IsEmpty()) {
if (aRect2.IsEmpty()) {
// Both rectangles are empty which is an error
Empty();
result = PR_FALSE;
} else {
// aRect1 is empty so set the result to aRect2
*this = aRect2;
}
} else if (aRect2.IsEmpty()) {
// aRect2 is empty so set the result to aRect1
*this = aRect1;
} else {
nscoord xmost1 = aRect1.XMost();
nscoord xmost2 = aRect2.XMost();
nscoord ymost1 = aRect1.YMost();
nscoord ymost2 = aRect2.YMost();
// Compute the origin
x = MIN(aRect1.x, aRect2.x);
y = MIN(aRect1.y, aRect2.y);
// Compute the size
width = MAX(xmost1, xmost2) - x;
height = MAX(ymost1, ymost2) - y;
}
return result;
}
// Inflate the rect by the specified width and height
void nsRect::Inflate(nscoord aDx, nscoord aDy)
{
x -= aDx;
y -= aDy;
width += 2 * aDx;
height += 2 * aDy;
}
// Inflate the rect by the specified margin
void nsRect::Inflate(const nsMargin &aMargin)
{
x -= aMargin.left;
y -= aMargin.top;
width += aMargin.left + aMargin.right;
height += aMargin.top + aMargin.bottom;
}
// Deflate the rect by the specified width and height
void nsRect::Deflate(nscoord aDx, nscoord aDy)
{
x += aDx;
y += aDy;
width -= 2 * aDx;
height -= 2 * aDy;
}
// Deflate the rect by the specified margin
void nsRect::Deflate(const nsMargin &aMargin)
{
x += aMargin.left;
y += aMargin.top;
width -= aMargin.left + aMargin.right;
height -= aMargin.top + aMargin.bottom;
}
// Diagnostics
FILE* operator<<(FILE* out, const nsRect& rect)
{
nsAutoString tmp;
// Output the coordinates in fractional points so they're easier to read
tmp.Append("{");
tmp.Append(NS_TWIPS_TO_POINTS_FLOAT(rect.x));
tmp.Append(", ");
tmp.Append(NS_TWIPS_TO_POINTS_FLOAT(rect.y));
tmp.Append(", ");
tmp.Append(NS_TWIPS_TO_POINTS_FLOAT(rect.width));
tmp.Append(", ");
tmp.Append(NS_TWIPS_TO_POINTS_FLOAT(rect.height));
tmp.Append("}");
fputs(tmp, out);
return out;
}

129
mozilla/gfx/src/nsRect.h Normal file
View File

@@ -0,0 +1,129 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef NSRECT_H
#define NSRECT_H
#include <stdio.h>
#include "nsCoord.h"
#include "nsPoint.h"
#include "nsSize.h"
#include "nsMargin.h"
#include "nsUnitConversion.h"
struct NS_GFX nsRect {
nscoord x, y;
nscoord width, height;
// Constructors
nsRect() {}
nsRect(const nsRect& aRect) {*this = aRect;}
nsRect(const nsPoint& aOrigin, const nsSize &aSize) {x = aOrigin.x; y = aOrigin.y;
width = aSize.width; height = aSize.height;}
nsRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight) {x = aX; y = aY;
width = aWidth; height = aHeight;}
// Emptiness. An empty rect is one that has no area, i.e. its width or height
// is <= 0
PRBool IsEmpty() const {
return (PRBool) ((width <= 0) || (height <= 0));
}
void Empty() {width = height = 0;}
// Containment
PRBool Contains(const nsRect& aRect) const;
PRBool Contains(nscoord aX, nscoord aY) const;
PRBool Contains(const nsPoint& aPoint) const {return Contains(aPoint.x, aPoint.y);}
// Intersection. Returns TRUE if the receiver overlaps aRect and
// FALSE otherwise
PRBool Intersects(const nsRect& aRect) const;
// Computes the area in which aRect1 and aRect2 overlap, and fills 'this' with
// the result. Returns FALSE if the rectangles don't intersect, and sets 'this'
// rect to be an empty rect.
//
// 'this' can be the same object as either aRect1 or aRect2
PRBool IntersectRect(const nsRect& aRect1, const nsRect& aRect2);
// Computes the smallest rectangle that contains both aRect1 and aRect2 and
// fills 'this' with the result. Returns FALSE and sets 'this' rect to be an
// empty rect if both aRect1 and aRect2 are empty
//
// 'this' can be the same object as either aRect1 or aRect2
PRBool UnionRect(const nsRect& aRect1, const nsRect& aRect2);
// Accessors
void SetRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight) {
x = aX; y = aY; width = aWidth; height = aHeight;
}
void MoveTo(nscoord aX, nscoord aY) {x = aX; y = aY;}
void MoveTo(const nsPoint& aPoint) {x = aPoint.y; y = aPoint.y;}
void MoveBy(nscoord aDx, nscoord aDy) {x += aDx; y += aDy;}
void SizeTo(nscoord aWidth, nscoord aHeight) {width = aWidth; height = aHeight;}
void SizeTo(const nsSize& aSize) {SizeTo(aSize.width, aSize.height);}
void SizeBy(nscoord aDeltaWidth, nscoord aDeltaHeight) {width += aDeltaWidth;
height += aDeltaHeight;}
// Inflate the rect by the specified width/height or margin
void Inflate(nscoord aDx, nscoord aDy);
void Inflate(const nsSize& aSize) {Inflate(aSize.width, aSize.height);}
void Inflate(const nsMargin& aMargin);
// Deflate the rect by the specified width/height or margin
void Deflate(nscoord aDx, nscoord aDy);
void Deflate(const nsSize& aSize) {Deflate(aSize.width, aSize.height);}
void Deflate(const nsMargin& aMargin);
// Overloaded operators. Note that '=' isn't defined so we'll get the
// compiler generated default assignment operator.
PRBool operator==(const nsRect& aRect) const {
return (PRBool) ((IsEmpty() && aRect.IsEmpty()) ||
((x == aRect.x) && (y == aRect.y) &&
(width == aRect.width) && (height == aRect.height)));
}
PRBool operator!=(const nsRect& aRect) const {
return (PRBool) !operator==(aRect);
}
nsRect operator+(const nsRect& aRect) const {
return nsRect(x + aRect.x, y + aRect.y,
width + aRect.width, height + aRect.height);
}
nsRect operator-(const nsRect& aRect) const {
return nsRect(x - aRect.x, y - aRect.y,
width - aRect.width, height - aRect.height);
}
nsRect& operator+=(const nsPoint& aPoint) {x += aPoint.x; y += aPoint.y; return *this;}
nsRect& operator-=(const nsPoint& aPoint) {x -= aPoint.x; y -= aPoint.y; return *this;}
nsRect& operator*=(const float aScale) {x = NS_TO_INT_ROUND(x * aScale);
y = NS_TO_INT_ROUND(y * aScale);
width = NS_TO_INT_ROUND(width * aScale);
height = NS_TO_INT_ROUND(height * aScale);
return *this;}
// Helper methods for computing the extents
nscoord XMost() const {return x + width;}
nscoord YMost() const {return y + height;}
};
// Diagnostics
extern NS_GFX FILE* operator<<(FILE* out, const nsRect& rect);
#endif /* NSRECT_H */

160
mozilla/gfx/src/nsRegion.h Normal file
View File

@@ -0,0 +1,160 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsRegion_h___
#define nsRegion_h___
#include "nscore.h"
#include "nsRect.h"
// Function type passed into nsRegion::forEachRect, invoked
// for each rectangle in a region
typedef void (*nsRectInRegionFunc)(void *closure, nsRect& rect);
// An implementation of a region primitive that can be used to
// represent arbitrary pixel areas. Probably implemented on top
// of the native region primitive. The assumption is that, at worst,
// it is a rectangle list.
class nsRegion : public nsObjBase
{
public:
/**
* copy operator equivalent that takes another region
*
* @param region to copy
* @return void
*
**/
virtual void setRegion(const nsRegion* region) = 0;
/**
* copy operator equivalent that takes a rect
*
* @param rect to copy
* @return void
*
**/
virtual void setRect(const nsRect* rect) = 0;
/**
* destructively intersect another region with this one
*
* @param region to intersect
* @return void
*
**/
virtual void intersect(const nsRegion* region) = 0;
/**
* destructively intersect a rect with this region
*
* @param rect to intersect
* @return void
*
**/
virtual void intersect(const nsRect* rect) = 0;
/**
* destructively union another region with this one
*
* @param region to union
* @return void
*
**/
virtual void union(const nsRegion* region) = 0;
/**
* destructively union a rect with this region
*
* @param rect to union
* @return void
*
**/
virtual void union(const nsRect* rect) = 0;
/**
* destructively subtract another region with this one
*
* @param region to subtract
* @return void
*
**/
virtual void subtract(const nsRegion* region) = 0;
/**
* is this region empty? i.e. does it contain any pixels
*
* @param none
* @return returns whether the region is empty
*
**/
virtual nsbool isEmpty() = 0;
/**
* == operator equivalent i.e. do the regions contain exactly
* the same pixels
*
* @param region to compare
* @return whether the regions are identical
*
**/
virtual nsbool isEqual(const nsRegion* region) = 0;
/**
* returns the bounding box of the region i.e. the smallest
* rectangle that completely contains the region.
*
* @param rect to set to the bounding box
* @return void
*
**/
virtual void getBoundingBox(nsRect* rect) = 0;
/**
* offsets the region in x and y
*
* @param xoffset pixel offset in x
* @param yoffset pixel offset in y
* @return void
*
**/
virtual void offset(nsfloat xoffset, nsfloat yoffset) = 0;
/**
* does the region completely contain the rectangle?
*
* @param rect to check for containment
* @return true iff the rect is completely contained
*
**/
virtual nsbool containsRect(const nsRect* rect) = 0;
/**
* invoke a function for each rectangle in the region
*
* @param func Function to invoke for each rectangle
* @param closure Arbitrary data to pass to the function
* @return void
*
**/
virtual void forEachRect(nsRectInRegionFunc* func, void* closure) = 0;
};
extern NS_GFX nsRegion* NS_NewRegion(nsPresentationContext* context);
#endif // nsRegion_h___

61
mozilla/gfx/src/nsSize.h Normal file
View File

@@ -0,0 +1,61 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef NSSIZE_H
#define NSSIZE_H
#include "nsCoord.h"
// Maximum allowable size
#define NS_MAXSIZE nscoord(1 << 30)
struct nsSize {
nscoord width, height;
// Constructors
nsSize() {}
nsSize(const nsSize& aSize) {width = aSize.width; height = aSize.height;}
nsSize(nscoord aWidth, nscoord aHeight) {width = aWidth; height = aHeight;}
void SizeTo(nscoord aWidth, nscoord aHeight) {width = aWidth; height = aHeight;}
void SizeBy(nscoord aDeltaWidth, nscoord aDeltaHeight) {width += aDeltaWidth;
height += aDeltaHeight;}
// Overloaded operators. Note that '=' isn't defined so we'll get the
// compiler generated default assignment operator
PRBool operator==(const nsSize& aSize) const {
return (PRBool) ((width == aSize.width) && (height == aSize.height));
}
PRBool operator!=(const nsSize& aSize) const {
return (PRBool) ((width != aSize.width) || (height != aSize.height));
}
nsSize operator+(const nsSize& aSize) const {
return nsSize(width + aSize.width, height + aSize.height);
}
nsSize operator-(const nsSize& aSize) const {
return nsSize(width - aSize.width, height - aSize.height);
}
nsSize& operator+=(const nsSize& aSize) {width += aSize.width;
height += aSize.height;
return *this;}
nsSize& operator-=(const nsSize& aSize) {width -= aSize.width;
height -= aSize.height;
return *this;}
};
#endif /* NSSIZE_H */

View File

@@ -0,0 +1,565 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsTransform2D.h"
void nsTransform2D :: SetToScale(float sx, float sy)
{
m01 = m10 = m20 = m21 = 0.0f;
m00 = sx;
m11 = sy;
type = MG_2DSCALE;
}
void nsTransform2D :: SetToTranslate(float tx, float ty)
{
m01 = m10 = 0.0f;
m00 = m11 = 1.0f;
m20 = tx;
m21 = ty;
type = MG_2DTRANSLATION;
}
void nsTransform2D :: SetMatrix(nsTransform2D *aTransform2D)
{
m00 = aTransform2D->m00;
m01 = aTransform2D->m01;
m10 = aTransform2D->m10;
m11 = aTransform2D->m11;
m20 = aTransform2D->m20;
m21 = aTransform2D->m21;
type = aTransform2D->type;
}
void nsTransform2D :: Concatenate(nsTransform2D *newxform)
{
float temp00, temp01, temp10, temp11;
float new00, new01, new10, new11, new20, new21;
PRUint16 newtype = newxform->type;
if (type == MG_2DIDENTITY)
{
//current matrix is identity
if (newtype != MG_2DIDENTITY)
SetMatrix(newxform);
return;
}
else if (newtype == MG_2DIDENTITY)
return;
else if ((type & MG_2DSCALE) != 0)
{
//current matrix is at least scale
if ((newtype & (MG_2DGENERAL | MG_2DSCALE)) != 0)
{
//new matrix is general or scale
if ((newtype & MG_2DTRANSLATION) != 0)
{
m20 += newxform->m20 * m00;
m21 += newxform->m21 * m11;
}
m00 *= newxform->m00;
m11 *= newxform->m11;
}
else
{
//new matrix must be translation only
m20 += newxform->m20 * m00;
m21 += newxform->m21 * m11;
}
}
else if ((type & MG_2DGENERAL) != 0)
{
//current matrix is at least general
if ((newtype & MG_2DGENERAL) != 0)
{
//new matrix is general - worst case
temp00 = m00;
temp01 = m01;
temp10 = m10;
temp11 = m11;
new00 = newxform->m00;
new01 = newxform->m01;
new10 = newxform->m10;
new11 = newxform->m11;
if ((newtype & MG_2DTRANSLATION) != 0)
{
new20 = newxform->m20;
new21 = newxform->m21;
m20 += new20 * temp00 + new21 * temp10;
m21 += new20 * temp01 + new21 * temp11;
}
m00 = new00 * temp00 + new01 * temp10;
m01 = new00 * temp01 + new01 * temp11;
m10 = new10 * temp00 + new11 * temp10;
m11 = new10 * temp01 + new11 * temp11;
}
else if ((newtype & MG_2DSCALE) != 0)
{
//new matrix is at least scale
temp00 = m00;
temp01 = m01;
temp10 = m10;
temp11 = m11;
new00 = newxform->m00;
new11 = newxform->m11;
if ((newtype & MG_2DTRANSLATION) != 0)
{
new20 = newxform->m20;
new21 = newxform->m21;
m20 += new20 * temp00 + new21 * temp10;
m21 += new20 * temp01 + new21 * temp11;
}
m00 = new00 * temp00;
m01 = new00 * temp01;
m10 = new11 * temp10;
m11 = new11 * temp11;
}
else
{
//new matrix must be translation only
new20 = newxform->m20;
new21 = newxform->m21;
m20 += new20 * m00 + new21 * m10;
m21 += new20 * m01 + new21 * m11;
}
}
else
{
//current matrix is translation only
if ((newtype & (MG_2DGENERAL | MG_2DSCALE)) != 0)
{
//new matrix is general or scale
if ((newtype & MG_2DTRANSLATION) != 0)
{
m20 += newxform->m20;
m21 += newxform->m21;
}
m00 = newxform->m00;
m11 = newxform->m11;
}
else
{
//new matrix must be translation only
m20 += newxform->m20;
m21 += newxform->m21;
}
}
/* temp00 = m00;
temp01 = m01;
temp10 = m10;
temp11 = m11;
temp20 = m20;
temp21 = m21;
new00 = newxform.m00;
new01 = newxform.m01;
new10 = newxform.m10;
new11 = newxform.m11;
new20 = newxform.m20;
new21 = newxform.m21;
m00 = new00 * temp00 + new01 * temp10; // + new02 * temp20 == 0
m01 = new00 * temp01 + new01 * temp11; // + new02 * temp21 == 0
// m02 += new00 * temp02 + new01 * temp12; // + new02 * temp22 == 0
m10 = new10 * temp00 + new11 * temp10; // + new12 * temp20 == 0
m11 = new10 * temp01 + new11 * temp11; // + new12 * temp21 == 0
// m12 += new10 * temp02 + new11 * temp12; // + new12 * temp22 == 0
m20 = new20 * temp00 + new21 * temp10 + temp20; // + new22 * temp20 == temp20
m21 = new20 * temp01 + new21 * temp11 + temp21; // + new22 * temp21 == temp21
// m22 += new20 * temp02 + new21 * temp12; // + new22 * temp22 == 1
*/
type |= newtype;
}
void nsTransform2D :: PreConcatenate(nsTransform2D *newxform)
{
float temp00, temp01, temp10, temp11, temp20, temp21;
float new00, new01, new10, new11;
//this is totally unoptimized MMP
temp00 = m00;
temp01 = m01;
temp10 = m10;
temp11 = m11;
temp20 = m20;
temp21 = m21;
new00 = newxform->m00;
new01 = newxform->m01;
new10 = newxform->m10;
new11 = newxform->m11;
m00 = temp00 * new00 + temp01 * new10; // + temp02 * new20 == 0
m01 = temp00 * new01 + temp01 * new11; // + temp02 * new21 == 0
// m02 += temp00 * new02 + temp01 * new12; // + temp02 * new22 == 0
m10 = temp10 * new00 + temp11 * new10; // + temp12 * new20 == 0
m11 = temp10 * new01 + temp11 * new11; // + temp12 * new21 == 0
// m12 += temp10 * new02 + temp11 * new12; // + temp12 * new22 == 0
m20 = temp20 * new00 + temp21 * temp10 + temp20; // + temp22 * new20 == new20
m21 = temp20 * new01 + temp21 * new11 + temp21; // + temp22 * new21 == new21
// m22 += temp20 * new02 + temp21 * new12; // + temp22 * new22 == 1
type |= newxform->type;
}
void nsTransform2D :: TransformNoXLate(float *ptX, float *ptY)
{
float x, y;
switch (type)
{
case MG_2DIDENTITY:
break;
case MG_2DSCALE:
*ptX *= m00;
*ptY *= m11;
break;
default:
case MG_2DGENERAL:
x = *ptX;
y = *ptY;
*ptX = x * m00 + y * m10;
*ptY = x * m01 + y * m11;
break;
}
}
void nsTransform2D :: TransformNoXLateCoord(nscoord *ptX, nscoord *ptY)
{
float x, y;
switch (type)
{
case MG_2DIDENTITY:
break;
case MG_2DSCALE:
*ptX = NS_TO_INT_ROUND(*ptX * m00);
*ptY = NS_TO_INT_ROUND(*ptY * m11);
break;
default:
case MG_2DGENERAL:
x = (float)*ptX;
y = (float)*ptY;
*ptX = NS_TO_INT_ROUND(x * m00 + y * m10);
*ptY = NS_TO_INT_ROUND(x * m01 + y * m11);
break;
}
}
void nsTransform2D :: Transform(float *ptX, float *ptY)
{
float x, y;
switch (type)
{
case MG_2DIDENTITY:
break;
case MG_2DTRANSLATION:
*ptX += m20;
*ptY += m21;
break;
case MG_2DSCALE:
*ptX *= m00;
*ptY *= m11;
break;
case MG_2DGENERAL:
x = *ptX;
y = *ptY;
*ptX = x * m00 + y * m10;
*ptY = x * m01 + y * m11;
break;
case MG_2DSCALE | MG_2DTRANSLATION:
*ptX = *ptX * m00 + m20;
*ptY = *ptY * m11 + m21;
break;
default:
case MG_2DGENERAL | MG_2DTRANSLATION:
x = *ptX;
y = *ptY;
*ptX = x * m00 + y * m10 + m20;
*ptY = x * m01 + y * m11 + m21;
break;
}
}
void nsTransform2D :: TransformCoord(nscoord *ptX, nscoord *ptY)
{
float x, y;
switch (type)
{
case MG_2DIDENTITY:
break;
case MG_2DTRANSLATION:
*ptX += NS_TO_INT_ROUND(m20);
*ptY += NS_TO_INT_ROUND(m21);
break;
case MG_2DSCALE:
*ptX = NS_TO_INT_ROUND(*ptX * m00);
*ptY = NS_TO_INT_ROUND(*ptY * m11);
break;
case MG_2DGENERAL:
x = (float)*ptX;
y = (float)*ptY;
*ptX = NS_TO_INT_ROUND(x * m00 + y * m10);
*ptY = NS_TO_INT_ROUND(x * m01 + y * m11);
break;
case MG_2DSCALE | MG_2DTRANSLATION:
*ptX = NS_TO_INT_ROUND(*ptX * m00 + m20);
*ptY = NS_TO_INT_ROUND(*ptY * m11 + m21);
break;
default:
case MG_2DGENERAL | MG_2DTRANSLATION:
x = (float)*ptX;
y = (float)*ptY;
*ptX = NS_TO_INT_ROUND(x * m00 + y * m10 + m20);
*ptY = NS_TO_INT_ROUND(x * m01 + y * m11 + m21);
break;
}
}
void nsTransform2D :: Transform(float *aX, float *aY, float *aWidth, float *aHeight)
{
float x, y;
switch (type)
{
case MG_2DIDENTITY:
break;
case MG_2DTRANSLATION:
*aX += m20;
*aY += m21;
break;
case MG_2DSCALE:
*aX *= m00;
*aY *= m11;
*aWidth *= m00;
*aHeight *= m11;
break;
case MG_2DGENERAL:
x = *aX;
y = *aY;
*aX = x * m00 + y * m10;
*aY = x * m01 + y * m11;
x = *aWidth;
y = *aHeight;
*aHeight = x * m00 + y * m10;
*aHeight = x * m01 + y * m11;
break;
case MG_2DSCALE | MG_2DTRANSLATION:
*aX = *aX * m00 + m20;
*aY = *aY * m11 + m21;
*aWidth *= m00;
*aHeight *= m11;
break;
default:
case MG_2DGENERAL | MG_2DTRANSLATION:
x = *aX;
y = *aY;
*aX = x * m00 + y * m10 + m20;
*aY = x * m01 + y * m11 + m21;
x = *aWidth;
y = *aHeight;
*aWidth = x * m00 + y * m10;
*aHeight = x * m01 + y * m11;
break;
}
}
void nsTransform2D :: TransformCoord(nscoord *aX, nscoord *aY, nscoord *aWidth, nscoord *aHeight)
{
float x, y;
switch (type)
{
case MG_2DIDENTITY:
break;
case MG_2DTRANSLATION:
*aX += NS_TO_INT_ROUND(m20);
*aY += NS_TO_INT_ROUND(m21);
break;
case MG_2DSCALE:
*aX = NS_TO_INT_ROUND(*aX * m00);
*aY = NS_TO_INT_ROUND(*aY * m11);
*aWidth = NS_TO_INT_ROUND(*aWidth * m00);
*aHeight = NS_TO_INT_ROUND(*aHeight * m11);
break;
case MG_2DGENERAL:
x = (float)*aX;
y = (float)*aY;
*aX = NS_TO_INT_ROUND(x * m00 + y * m10);
*aY = NS_TO_INT_ROUND(x * m01 + y * m11);
x = (float)*aWidth;
y = (float)*aHeight;
*aHeight = NS_TO_INT_ROUND(x * m00 + y * m10);
*aHeight = NS_TO_INT_ROUND(x * m01 + y * m11);
break;
case MG_2DSCALE | MG_2DTRANSLATION:
*aX = NS_TO_INT_ROUND(*aX * m00 + m20);
*aY = NS_TO_INT_ROUND(*aY * m11 + m21);
*aWidth = NS_TO_INT_ROUND(*aWidth * m00);
*aHeight = NS_TO_INT_ROUND(*aHeight * m11);
break;
default:
case MG_2DGENERAL | MG_2DTRANSLATION:
x = (float)*aX;
y = (float)*aY;
*aX = NS_TO_INT_ROUND(x * m00 + y * m10 + m20);
*aY = NS_TO_INT_ROUND(x * m01 + y * m11 + m21);
x = (float)*aWidth;
y = (float)*aHeight;
*aWidth = NS_TO_INT_ROUND(x * m00 + y * m10);
*aHeight = NS_TO_INT_ROUND(x * m01 + y * m11);
break;
}
}
void nsTransform2D :: AddTranslation(float ptX, float ptY)
{
if (type == MG_2DIDENTITY)
{
m20 = ptX;
m21 = ptY;
}
else if ((type & MG_2DSCALE) != 0)
{
//current matrix is at least scale
m20 += ptX * m00;
m21 += ptY * m11;
}
else if ((type & MG_2DGENERAL) != 0)
{
//current matrix is at least general
m20 += ptX * m00 + ptY * m10;
m21 += ptX * m01 + ptY * m11;
}
else
{
m20 += ptX;
m21 += ptY;
}
type |= MG_2DTRANSLATION;
}
void nsTransform2D :: AddScale(float ptX, float ptY)
{
if ((type == MG_2DIDENTITY) || (type == MG_2DTRANSLATION))
{
m00 = ptX;
m11 = ptY;
}
else if ((type & MG_2DSCALE) != 0)
{
//current matrix is at least scale
m00 *= ptX;
m11 *= ptY;
}
else if ((type & MG_2DGENERAL) != 0)
{
//current matrix is at least general
m00 *= ptX;
m01 *= ptX;
m10 *= ptY;
m11 *= ptY;
}
type |= MG_2DSCALE;
}

View File

@@ -0,0 +1,211 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsTransform2D_h___
#define nsTransform2D_h___
#include "nscore.h"
#include "nsCoord.h"
#include "nsUnitConversion.h"
#define MG_2DIDENTITY 0
#define MG_2DTRANSLATION 1
#define MG_2DSCALE 2
#define MG_2DGENERAL 4
class NS_GFX nsTransform2D
{
private:
//accelerators
float m00, m01, m10, m11, m20, m21;
PRUint16 type;
public:
//constructors
nsTransform2D(void) { SetToIdentity(); }
nsTransform2D(nsTransform2D *aTransform2D) { SetMatrix(aTransform2D); }
//destructor
~nsTransform2D(void) { }
/**
* get the type of this transform
*
* @param
* @return type from above set
* @exception
* @author michaelp 09-25-97 1:56pm
**/
PRUint16 GetType(void) { return type; }
/**
* set this transform to identity
*
* @param
* @exception
* @author michaelp 09-25-97 1:56pm
**/
void SetToIdentity(void) { m01 = m10 = m20 = m21 = 0.0f; m00 = m11 = 1.0f; type = MG_2DIDENTITY; }
/**
* set this transform to a scale
*
* @param sx, x scale
* @param sy, y scale
* @exception
* @author michaelp 09-25-97 1:56pm
**/
void SetToScale(float sx, float sy);
/**
* set this transform to a translation
*
* @param tx, x translation
* @param ty, y translation
* @exception
* @author michaelp 09-25-97 1:56pm
**/
void SetToTranslate(float tx, float ty);
/**
* get the translation portion of this transform
*
* @param pt, Point to return translation values in
* @exception
* @author michaelp 09-25-97 1:56pm
**/
void GetTranslation(float *ptX, float *ptY) { *ptX = m20; *ptY = m21; }
void GetTranslationCoord(nscoord *ptX, nscoord *ptY) { *ptX = NS_TO_INT_ROUND(m20); *ptY = NS_TO_INT_ROUND(m21); }
/**
* get the X translation portion of this transform
*
* @param
* @returns x component of translation
* @exception
**/
float GetXTranslation(void) { return m20; }
nscoord GetXTranslationCoord(void) { return NS_TO_INT_ROUND(m20); }
/**
* get the Y translation portion of this transform
*
* @param
* @returns y component of translation
* @exception
**/
float GetYTranslation(void) { return m21; }
nscoord GetYTranslationCoord(void) { return NS_TO_INT_ROUND(m21); }
/**
* set this matrix and type from another Transform2D
*
* @param aTransform2D is the Transform2D to be copied from
* @exception
* @author michaelp 09-25-97 1:56pm
**/
void SetMatrix(nsTransform2D *aTransform2D);
/**
* post-multiply a new Transform
*
* @param newxform new Transform2D
* @exception
* @author michaelp 09-25-97 1:56pm
**/
void Concatenate(nsTransform2D *newxform);
/**
* pre-multiply a new Transform
*
* @param newxform new Transform2D
* @exception
* @author michaelp 09-25-97 1:56pm
**/
void PreConcatenate(nsTransform2D *newxform);
/**
* apply nontranslation portion of matrix to vector
*
* @param pt Point to transform
* @exception
* @author michaelp 09-25-97 1:56pm
**/
void TransformNoXLate(float *ptX, float *ptY);
void TransformNoXLateCoord(nscoord *ptX, nscoord *ptY);
/**
* apply matrix to vector
*
* @param pt Point to transform
* @exception
* @author michaelp 09-25-97 1:56pm
**/
void Transform(float *ptX, float *ptY);
void TransformCoord(nscoord *ptX, nscoord *ptY);
/**
* apply matrix to rect
*
* @param rect Rect to transform
* @exception
* @author michaelp 09-25-97 1:56pm
**/
void Transform(float *aX, float *aY, float *aWidth, float *aHeight);
void TransformCoord(nscoord *aX, nscoord *aY, nscoord *aWidth, nscoord *aHeight);
/**
* add a translation to a Transform via x, y pair
*
* @param ptX x value to add as x translation
* @param ptY y value to add as y translation
* @exception
* @author michaelp 09-25-97 1:56pm
**/
void AddTranslation(float ptX, float ptY);
/**
* add a scale to a Transform via x, y pair
*
* @param ptX x value to add as x scale
* @param ptY y value to add as y scale
* @exception
* @author michaelp 09-25-97 1:56pm
**/
void AddScale(float ptX, float ptY);
};
#endif

View File

@@ -0,0 +1,60 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=..\..\..
IGNORE_MANIFEST=1
MAKE_OBJ_TYPE = DLL
DLLNAME = raptorgfxwin
DLL=.\$(OBJDIR)\$(DLLNAME).dll
#RESFILE = $(DLLNAME).res
MODULE=raptor
DEFINES =-D_IMPL_NS_GFXNONXP -DWIN32_LEAN_AND_MEAN
OBJS = \
.\$(OBJDIR)\nsDeviceContextWin.obj \
.\$(OBJDIR)\nsRenderingContextWin.obj \
.\$(OBJDIR)\nsFontMetricsWin.obj \
.\$(OBJDIR)\nsImageWin.obj \
.\$(OBJDIR)\nsGfxFactoryWin.obj \
$(NULL)
LINCS= \
-I$(PUBLIC)\raptor \
-I$(PUBLIC)\xpcom \
$(NULL)
LCFLAGS = \
$(LCFLAGS) \
-D_IMPL_NS_GFXNONXP \
$(NULL)
LLIBS= \
$(DIST)\lib\xpcom32.lib \
$(DIST)\lib\raptorbase.lib \
$(DIST)\lib\raptorgfx.lib \
$(LIBNSPR)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin
clobber::
rm -f $(DIST)\bin\$(DLLNAME).dll

View File

@@ -0,0 +1,229 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsDeviceContextWin.h"
#include "nsRenderingContextWin.h"
#include "../nsGfxCIID.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kDeviceContextIID, NS_IDEVICE_CONTEXT_IID);
nsDeviceContextWin :: nsDeviceContextWin()
{
NS_INIT_REFCNT();
HDC hdc = ::GetDC(NULL);
mTwipsToPixels = ::GetDeviceCaps(hdc, LOGPIXELSX) / NS_POINTS_TO_TWIPS_FLOAT(72.0f);
mPixelsToTwips = 1.0f / mTwipsToPixels;
::ReleaseDC(NULL, hdc);
mFontCache = nsnull;
mDevUnitsToAppUnits = 1.0f;
mAppUnitsToDevUnits = 1.0f;
mGammaValue = 1.0f;
mGammaTable = new PRUint8[256];
mZoom = 1.0f;
mSurface = NULL;
}
nsDeviceContextWin :: ~nsDeviceContextWin()
{
NS_IF_RELEASE(mFontCache);
if (NULL != mSurface)
{
DeleteDC(mSurface);
mSurface = NULL;
}
if (nsnull != mGammaTable)
{
delete mGammaTable;
mGammaTable = nsnull;
}
}
NS_IMPL_QUERY_INTERFACE(nsDeviceContextWin, kDeviceContextIID)
NS_IMPL_ADDREF(nsDeviceContextWin)
NS_IMPL_RELEASE(nsDeviceContextWin)
nsresult nsDeviceContextWin :: Init()
{
for (PRInt32 cnt = 0; cnt < 256; cnt++)
mGammaTable[cnt] = cnt;
return NS_OK;
}
float nsDeviceContextWin :: GetTwipsToDevUnits() const
{
return mTwipsToPixels;
}
float nsDeviceContextWin :: GetDevUnitsToTwips() const
{
return mPixelsToTwips;
}
void nsDeviceContextWin :: SetAppUnitsToDevUnits(float aAppUnits)
{
mAppUnitsToDevUnits = aAppUnits;
}
void nsDeviceContextWin :: SetDevUnitsToAppUnits(float aDevUnits)
{
mDevUnitsToAppUnits = aDevUnits;
}
float nsDeviceContextWin :: GetAppUnitsToDevUnits() const
{
return mAppUnitsToDevUnits;
}
float nsDeviceContextWin :: GetDevUnitsToAppUnits() const
{
return mDevUnitsToAppUnits;
}
float nsDeviceContextWin :: GetScrollBarWidth() const
{
return ::GetSystemMetrics(SM_CXVSCROLL) * mDevUnitsToAppUnits;
}
float nsDeviceContextWin :: GetScrollBarHeight() const
{
return ::GetSystemMetrics(SM_CXHSCROLL) * mDevUnitsToAppUnits;
}
nsIRenderingContext * nsDeviceContextWin :: CreateRenderingContext(nsIView *aView)
{
nsIRenderingContext *pContext = nsnull;
nsIWidget *win = aView->GetWidget();
nsresult rv;
static NS_DEFINE_IID(kRCCID, NS_RENDERING_CONTEXT_CID);
static NS_DEFINE_IID(kRCIID, NS_IRENDERING_CONTEXT_IID);
rv = NSRepository::CreateInstance(kRCCID, nsnull, kRCIID, (void **)&pContext);
if (NS_OK == rv)
InitRenderingContext(pContext, win);
NS_IF_RELEASE(win);
return pContext;
}
void nsDeviceContextWin :: InitRenderingContext(nsIRenderingContext *aContext, nsIWidget *aWin)
{
aContext->Init(this, aWin);
}
nsIFontCache* nsDeviceContextWin::GetFontCache()
{
if (nsnull == mFontCache) {
if (NS_OK != CreateFontCache()) {
return nsnull;
}
}
NS_ADDREF(mFontCache);
return mFontCache;
}
void nsDeviceContextWin::FlushFontCache()
{
NS_RELEASE(mFontCache);
}
nsresult nsDeviceContextWin::CreateFontCache()
{
nsresult rv = NS_NewFontCache(&mFontCache);
if (NS_OK != rv) {
return rv;
}
mFontCache->Init(this);
return NS_OK;
}
nsIFontMetrics* nsDeviceContextWin::GetMetricsFor(const nsFont& aFont)
{
if (nsnull == mFontCache) {
if (NS_OK != CreateFontCache()) {
return nsnull;
}
}
return mFontCache->GetMetricsFor(aFont);
}
void nsDeviceContextWin :: SetZoom(float aZoom)
{
mZoom = aZoom;
}
float nsDeviceContextWin :: GetZoom() const
{
return mZoom;
}
nsDrawingSurface nsDeviceContextWin :: GetDrawingSurface(nsIRenderingContext &aContext)
{
if (NULL == mSurface)
mSurface = aContext.CreateDrawingSurface(nsnull);
return mSurface;
}
float nsDeviceContextWin :: GetGamma(void)
{
return mGammaValue;
}
void nsDeviceContextWin :: SetGamma(float aGamma)
{
if (aGamma != mGammaValue)
{
//we don't need to-recorrect existing images for this case
//so pass in 1.0 for the current gamma regardless of what it
//really happens to be. existing images will get a one time
//re-correction when they're rendered the next time. MMP
SetGammaTable(mGammaTable, 1.0f, aGamma);
mGammaValue = aGamma;
}
}
PRUint8 * nsDeviceContextWin :: GetGammaTable(void)
{
//XXX we really need to ref count this somehow. MMP
return mGammaTable;
}
void nsDeviceContextWin :: SetGammaTable(PRUint8 * aTable, float aCurrentGamma, float aNewGamma)
{
double fgval = (1.0f / aCurrentGamma) * (1.0f / aNewGamma);
for (PRInt32 cnt = 0; cnt < 256; cnt++)
aTable[cnt] = (PRUint8)(pow((double)cnt * (1. / 256.), fgval) * 255.99999999);
}

View File

@@ -0,0 +1,85 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsDeviceContextWin_h___
#define nsDeviceContextWin_h___
#include "nsIDeviceContext.h"
#include "nsUnitConversion.h"
#include "nsIFontCache.h"
#include "nsIWidget.h"
#include "nsIView.h"
#include "nsIRenderingContext.h"
#include <windows.h>
class nsDeviceContextWin : public nsIDeviceContext
{
public:
nsDeviceContextWin();
NS_DECL_ISUPPORTS
virtual nsresult Init();
virtual nsIRenderingContext * CreateRenderingContext(nsIView *aView);
virtual void InitRenderingContext(nsIRenderingContext *aContext, nsIWidget *aWidget);
virtual float GetTwipsToDevUnits() const;
virtual float GetDevUnitsToTwips() const;
virtual void SetAppUnitsToDevUnits(float aAppUnits);
virtual void SetDevUnitsToAppUnits(float aDevUnits);
virtual float GetAppUnitsToDevUnits() const;
virtual float GetDevUnitsToAppUnits() const;
virtual float GetScrollBarWidth() const;
virtual float GetScrollBarHeight() const;
virtual nsIFontCache * GetFontCache();
virtual void FlushFontCache();
virtual nsIFontMetrics* GetMetricsFor(const nsFont& aFont);
virtual void SetZoom(float aZoom);
virtual float GetZoom() const;
virtual nsDrawingSurface GetDrawingSurface(nsIRenderingContext &aContext);
virtual float GetGamma(void);
virtual void SetGamma(float aGamma);
virtual PRUint8 * GetGammaTable(void);
protected:
~nsDeviceContextWin();
nsresult CreateFontCache();
void SetGammaTable(PRUint8 * aTable, float aCurrentGamma, float aNewGamma);
float mTwipsToPixels;
float mPixelsToTwips;
float mAppUnitsToDevUnits;
float mDevUnitsToAppUnits;
nsIFontCache *mFontCache;
float mZoom;
HDC mSurface;
float mGammaValue;
PRUint8 *mGammaTable;
};
#endif /* nsDeviceContextWin_h___ */

View File

@@ -0,0 +1,237 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsFontMetricsWin.h"
static NS_DEFINE_IID(kIFontMetricsIID, NS_IFONT_METRICS_IID);
nsFontMetricsWin :: nsFontMetricsWin()
{
NS_INIT_REFCNT();
}
nsFontMetricsWin :: ~nsFontMetricsWin()
{
if (nsnull != mFont)
{
delete mFont;
mFont = nsnull;
}
}
NS_IMPL_ISUPPORTS(nsFontMetricsWin, kIFontMetricsIID)
// Note: The presentation context has a reference to this font
// metrics, therefore avoid circular references by not AddRef'ing the
// presentation context.
nsresult nsFontMetricsWin :: Init(const nsFont& aFont, nsIDeviceContext* aCX)
{
mFont = new nsFont(aFont);
mContext = aCX;
RealizeFont();
return NS_OK;
}
// XXX this function is a hack; the only logical font names we should
// support are the one used by css.
const char* nsFontMetricsWin::MapFamilyToFont(const nsString& aLogicalFontName)
{
if (aLogicalFontName.EqualsIgnoreCase("Times Roman")) {
return "Times New Roman";
}
if (aLogicalFontName.EqualsIgnoreCase("Times")) {
return "Times New Roman";
}
if (aLogicalFontName.EqualsIgnoreCase("Unicode")) {
return "Bitstream Cyberbit";
}
if (aLogicalFontName.EqualsIgnoreCase("Courier")) {
return "Courier New";
}
// the CSS generic names
if (aLogicalFontName.EqualsIgnoreCase("serif")) {
return "Times New Roman";
}
if (aLogicalFontName.EqualsIgnoreCase("sans-serif")) {
return "Arial";
}
if (aLogicalFontName.EqualsIgnoreCase("cursive")) {
// return "XXX";
}
if (aLogicalFontName.EqualsIgnoreCase("fantasy")) {
// return "XXX";
}
if (aLogicalFontName.EqualsIgnoreCase("monospace")) {
return "Courier New";
}
return "Arial";/* XXX for now */
}
void nsFontMetricsWin::RealizeFont()
{
// Fill in logFont structure; stolen from awt
LOGFONT logFont;
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;
logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
logFont.lfQuality = DEFAULT_QUALITY;
logFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
logFont.lfWeight = (mFont->weight > NS_FONT_WEIGHT_NORMAL) // XXX ??? this should be smarter
? FW_BOLD : FW_NORMAL;
logFont.lfItalic = (mFont->style & NS_FONT_STYLE_ITALIC)
? TRUE : FALSE;
float t2p = mContext->GetAppUnitsToDevUnits();
logFont.lfHeight = (LONG)(-mFont->size * t2p);
strncpy(logFont.lfFaceName,
MapFamilyToFont(mFont->name),
LF_FACESIZE);
// Create font handle from font spec
mFontHandle = ::CreateFontIndirect(&logFont);
//fprintf(stderr, "fFontHandle=%x\n", fFontHandle);
// Find font metrics and character widths
HWND win = ::GetDesktopWindow();
HDC dc = ::GetDC(win);
::SelectObject(dc, (HGDIOBJ) mFontHandle);
// Get font metrics
float p2t = mContext->GetDevUnitsToAppUnits();
TEXTMETRIC metrics;
::GetTextMetrics(dc, &metrics);
mHeight = nscoord(metrics.tmHeight * p2t);
mAscent = nscoord(metrics.tmAscent * p2t);
mDescent = nscoord(metrics.tmDescent * p2t);
mLeading = nscoord(metrics.tmInternalLeading * p2t);
mMaxAscent = nscoord(metrics.tmAscent * p2t);
mMaxDescent = nscoord(metrics.tmDescent * p2t);
mMaxAdvance = nscoord(metrics.tmMaxCharWidth * p2t);
#if 0
fprintf(stderr, "fontmetrics: height=%d ascent=%d descent=%d leading=%d\n",
fHeight, fAscent, fDescent, fLeading);
#endif
// Get character widths in twips
int widths[256];
::GetCharWidth(dc, 0, 255, widths);
nscoord* tp = mCharWidths;
int* fp = widths;
int* end = fp + 256;
while (fp < end) {
*tp++ = nscoord( *fp++ * p2t );
}
::ReleaseDC(win, dc);
}
nscoord nsFontMetricsWin :: GetWidth(char ch)
{
return mCharWidths[PRUint8(ch)];
}
nscoord nsFontMetricsWin :: GetWidth(PRUnichar ch)
{
if (ch < 256) {
return mCharWidths[ch];
}
return 0;/* XXX */
}
nscoord nsFontMetricsWin :: GetWidth(const nsString& aString)
{
return GetWidth(aString.GetUnicode(), aString.Length());
}
nscoord nsFontMetricsWin :: GetWidth(const char *aString)
{
// XXX use native text measurement routine
nscoord sum = 0;
PRUint8 ch;
while ((ch = PRUint8(*aString++)) != 0) {
sum += mCharWidths[ch];
}
return sum;
}
nscoord nsFontMetricsWin :: GetWidth(const PRUnichar *aString, PRUint32 aLength)
{
// XXX use native text measurement routine
nscoord sum = 0;
while (aLength != 0) {
PRUnichar ch = *aString++;
if (ch < 256) {
sum += mCharWidths[ch];
} else {
// XXX not yet
}
--aLength;
}
return sum;
}
nscoord nsFontMetricsWin :: GetHeight()
{
return mHeight;
}
nscoord nsFontMetricsWin :: GetLeading()
{
return mLeading;
}
nscoord nsFontMetricsWin :: GetMaxAscent()
{
return mMaxAscent;
}
nscoord nsFontMetricsWin :: GetMaxDescent()
{
return mMaxDescent;
}
nscoord nsFontMetricsWin :: GetMaxAdvance()
{
return mMaxAdvance;
}
const nscoord * nsFontMetricsWin :: GetWidths()
{
return mCharWidths;
}
const nsFont& nsFontMetricsWin :: GetFont()
{
return *mFont;
}
nsFontHandle nsFontMetricsWin::GetFontHandle()
{
return mFontHandle;
}

View File

@@ -0,0 +1,77 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsFontMetricsWin_h__
#define nsFontMetricsWin_h__
#include <windows.h>
#include "nsIFontMetrics.h"
#include "nsFont.h"
#include "nsString.h"
#include "nsUnitConversion.h"
#include "nsIDeviceContext.h"
#include "nsCRT.h"
class nsFontMetricsWin : public nsIFontMetrics
{
public:
nsFontMetricsWin();
~nsFontMetricsWin();
void* operator new(size_t sz) {
void* rv = new char[sz];
nsCRT::zero(rv, sz);
return rv;
}
NS_DECL_ISUPPORTS
virtual nsresult Init(const nsFont& aFont, nsIDeviceContext* aContext);
virtual nscoord GetWidth(char aC);
virtual nscoord GetWidth(PRUnichar aC);
virtual nscoord GetWidth(const nsString& aString);
virtual nscoord GetWidth(const char *aString);
virtual nscoord GetWidth(const PRUnichar *aString, PRUint32 aLength);
virtual nscoord GetHeight();
virtual nscoord GetLeading();
virtual nscoord GetMaxAscent();
virtual nscoord GetMaxDescent();
virtual nscoord GetMaxAdvance();
virtual const nscoord *GetWidths();
virtual const nsFont& GetFont();
virtual nsFontHandle GetFontHandle();
protected:
void RealizeFont();
static const char* MapFamilyToFont(const nsString& aLogicalFontName);
nsFont *mFont;
nsIDeviceContext *mContext;
nscoord mCharWidths[256];
nscoord mHeight;
nscoord mAscent;
nscoord mDescent;
nscoord mLeading;
nscoord mMaxAscent;
nscoord mMaxDescent;
nscoord mMaxAdvance;
HFONT mFontHandle;
};
#endif

View File

@@ -0,0 +1,171 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nscore.h"
#include "nsIFactory.h"
#include "nsISupports.h"
#include "../nsGfxCIID.h"
#include "nsFontMetricsWin.h"
#include "nsRenderingContextWin.h"
#include "nsImageWin.h"
#include "nsDeviceContextWin.h"
static NS_DEFINE_IID(kCFontMetrics, NS_FONT_METRICS_CID);
static NS_DEFINE_IID(kCRenderingContext, NS_RENDERING_CONTEXT_CID);
static NS_DEFINE_IID(kCImage, NS_IMAGE_CID);
static NS_DEFINE_IID(kCDeviceContext, NS_DEVICE_CONTEXT_CID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
class nsGfxFactoryWin : public nsIFactory
{
public:
// nsISupports methods
NS_IMETHOD QueryInterface(const nsIID &aIID,
void **aResult);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
// nsIFactory methods
NS_IMETHOD CreateInstance(nsISupports *aOuter,
const nsIID &aIID,
void **aResult);
NS_IMETHOD LockFactory(PRBool aLock);
nsGfxFactoryWin(const nsCID &aClass);
~nsGfxFactoryWin();
private:
nsrefcnt mRefCnt;
nsCID mClassID;
};
nsGfxFactoryWin::nsGfxFactoryWin(const nsCID &aClass)
{
mRefCnt = 0;
mClassID = aClass;
}
nsGfxFactoryWin::~nsGfxFactoryWin()
{
NS_ASSERTION(mRefCnt == 0, "non-zero refcnt at destruction");
}
nsresult nsGfxFactoryWin::QueryInterface(const nsIID &aIID,
void **aResult)
{
if (aResult == NULL) {
return NS_ERROR_NULL_POINTER;
}
// Always NULL result, in case of failure
*aResult = NULL;
if (aIID.Equals(kISupportsIID)) {
*aResult = (void *)(nsISupports*)this;
} else if (aIID.Equals(kIFactoryIID)) {
*aResult = (void *)(nsIFactory*)this;
}
if (*aResult == NULL) {
return NS_NOINTERFACE;
}
AddRef(); // Increase reference count for caller
return NS_OK;
}
nsrefcnt nsGfxFactoryWin::AddRef()
{
return ++mRefCnt;
}
nsrefcnt nsGfxFactoryWin::Release()
{
if (--mRefCnt == 0) {
delete this;
return 0; // Don't access mRefCnt after deleting!
}
return mRefCnt;
}
nsresult nsGfxFactoryWin::CreateInstance(nsISupports *aOuter,
const nsIID &aIID,
void **aResult)
{
if (aResult == NULL) {
return NS_ERROR_NULL_POINTER;
}
*aResult = NULL;
nsISupports *inst = nsnull;
if (mClassID.Equals(kCFontMetrics)) {
inst = (nsISupports *)new nsFontMetricsWin();
}
else if (mClassID.Equals(kCDeviceContext)) {
inst = (nsISupports *)new nsDeviceContextWin();
}
else if (mClassID.Equals(kCRenderingContext)) {
inst = (nsISupports *)new nsRenderingContextWin();
}
else if (mClassID.Equals(kCImage)) {
inst = (nsISupports *)new nsImageWin();
}
if (inst == NULL) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult res = inst->QueryInterface(aIID, aResult);
if (res != NS_OK) {
// We didn't get the right interface, so clean up
delete inst;
}
// else {
// inst->Release();
// }
return res;
}
nsresult nsGfxFactoryWin::LockFactory(PRBool aLock)
{
// Not implemented in simplest case.
return NS_OK;
}
// return the proper factory to the caller
extern "C" NS_GFXNONXP nsresult NSGetFactory(const nsCID &aClass, nsIFactory **aFactory)
{
if (nsnull == aFactory) {
return NS_ERROR_NULL_POINTER;
}
*aFactory = new nsGfxFactoryWin(aClass);
if (nsnull == aFactory) {
return NS_ERROR_OUT_OF_MEMORY;
}
return (*aFactory)->QueryInterface(kIFactoryIID, (void**)aFactory);
}

View File

@@ -0,0 +1,777 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsImageWin.h"
#include "nsRenderingContextWin.h"
static NS_DEFINE_IID(kIImageIID, NS_IIMAGE_IID);
//------------------------------------------------------------
nsImageWin :: nsImageWin()
{
NS_INIT_REFCNT();
mImageBits = nsnull;
mHBitmap = nsnull;
mHPalette = nsnull;
mAlphaBits = nsnull;
mColorMap = nsnull;
mBHead = nsnull;
CleanUp(PR_TRUE);
}
//------------------------------------------------------------
nsImageWin :: ~nsImageWin()
{
CleanUp(PR_TRUE);
}
NS_IMPL_ISUPPORTS(nsImageWin, kIImageIID);
//------------------------------------------------------------
nsresult nsImageWin :: Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth,nsMaskRequirements aMaskRequirements)
{
mHBitmap = nsnull;
mHPalette = nsnull;
CleanUp(PR_TRUE);
ComputePaletteSize(aDepth);
if (mNumPalleteColors >= 0)
{
mBHead = (LPBITMAPINFOHEADER) new char[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * mNumPalleteColors];
mBHead->biSize = sizeof(BITMAPINFOHEADER);
mBHead->biWidth = aWidth;
mBHead->biHeight = aHeight;
mBHead->biPlanes = 1;
mBHead->biBitCount = (unsigned short) aDepth;
mBHead->biCompression = BI_RGB;
mBHead->biSizeImage = 0; // not compressed, so we dont need this to be set
mBHead->biXPelsPerMeter = 0;
mBHead->biYPelsPerMeter = 0;
mBHead->biClrUsed = mNumPalleteColors;
mBHead->biClrImportant = mNumPalleteColors;
ComputeMetrics();
memset(mColorTable, 0, sizeof(RGBQUAD) * mNumPalleteColors);
mImageBits = new unsigned char[mSizeImage];
memset(mImageBits, 128, mSizeImage);
this->MakePalette();
if (aMaskRequirements != nsMaskRequirements_kNoMask)
{
mAlphaWidth=aWidth;
mAlphaWidth=aHeight;
mAlphaBits = new unsigned char[aWidth * aHeight];
}
else
{
mAlphaBits = 0;
mAlphaWidth=0;
mAlphaHeight=0;
}
mColorMap = new nsColorMap;
if (mColorMap != nsnull)
{
mColorMap->NumColors = mNumPalleteColors;
mColorMap->Index = new PRUint8[3 * mNumPalleteColors];
// XXX Note: I added this because purify claims that we make a
// copy of the memory (which we do!). I'm not sure if this
// matters or not, but this shutup purify.
memset(mColorMap->Index, 0, sizeof(PRUint8) * (3 * mNumPalleteColors));
}
}
return NS_OK;
}
//------------------------------------------------------------
// set up the pallete to the passed in color array, RGB only in this array
void nsImageWin :: ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect)
{
PRInt32 i;
PRUint8 *cpointer;
if (aFlags & nsImageUpdateFlags_kColorMapChanged)
{
PRUint8 *gamma = aContext->GetGammaTable();
if (mColorMap->NumColors > 0)
{
cpointer = mColorTable;
for(i = 0; i < mColorMap->NumColors; i++)
{
*cpointer++ = gamma[mColorMap->Index[(3 * i) + 2]];
*cpointer++ = gamma[mColorMap->Index[(3 * i) + 1]];
*cpointer++ = gamma[mColorMap->Index[(3 * i)]];
*cpointer++ = 0;
}
}
this->MakePalette();
}
else if ((aFlags & nsImageUpdateFlags_kBitsChanged) &&
(nsnull != aUpdateRect))
{
if (mNumPalleteColors == 0)
{
PRInt32 x, y, span = CalcBytesSpan(mBHead->biWidth), idx;
PRUint8 *pixels = mImageBits + aUpdateRect->y * span + aUpdateRect->x * 3;
PRUint8 *gamma = aContext->GetGammaTable();
for (y = 0; y < aUpdateRect->height; y++)
{
for (x = 0, idx = 0; x < aUpdateRect->width; x++)
{
pixels[idx] = gamma[pixels[idx]];
idx++;
pixels[idx] = gamma[pixels[idx]];
idx++;
pixels[idx] = gamma[pixels[idx]];
idx++;
}
pixels += span;
}
}
}
}
//------------------------------------------------------------
PRUintn nsImageWin :: UsePalette(HDC* aHdc, PRBool bBackground)
{
if (mHPalette == nsnull)
return 0;
HPALETTE hOldPalette = ::SelectPalette(aHdc, mHPalette, (bBackground == PR_TRUE) ? TRUE : FALSE);
return ::RealizePalette(aHdc);
}
//------------------------------------------------------------
// Draw the bitmap, this method has a source and destination coordinates
PRBool nsImageWin :: Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface, PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight,
PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight)
{
PRUint32 value,error;
HDC the_hdc = (HDC)aSurface;
if (mBHead == nsnull)
return PR_FALSE;
if (!IsOptimized())
{
value = ::StretchDIBits(the_hdc,aDX,aDY,aDWidth,aDHeight,
0,0,aSWidth, aSHeight,
mImageBits,(LPBITMAPINFO)mBHead,DIB_RGB_COLORS,SRCCOPY);
if (value == GDI_ERROR)
error = ::GetLastError();
}
else
{
nsIDeviceContext *dx = aContext.GetDeviceContext();
HDC srcdc = dx->GetDrawingSurface(aContext);
if (NULL != srcdc)
{
HBITMAP oldbits = ::SelectObject(srcdc, mHBitmap);
if (!::StretchBlt(the_hdc, aDX, aDY, aDWidth, aDHeight, srcdc, aSX, aSY,
aSWidth, aSHeight, SRCCOPY))
error = ::GetLastError();
if (nsnull != oldbits)
::SelectObject(srcdc, oldbits);
}
NS_RELEASE(dx);
}
return PR_TRUE;
}
//------------------------------------------------------------
// Draw the bitmap, this draw just has destination coordinates
PRBool nsImageWin :: Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface,
PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight)
{
PRUint32 value,error;
HDC the_hdc = (HDC)aSurface;
if (mBHead == nsnull)
return PR_FALSE;
if (!IsOptimized())
{
value = ::StretchDIBits(the_hdc,aX,aY,aWidth,aHeight,
0,0,mBHead->biWidth, mBHead->biHeight,
mImageBits,(LPBITMAPINFO)mBHead,DIB_RGB_COLORS,SRCCOPY);
if (value == GDI_ERROR)
error = ::GetLastError();
}
else
{
nsIDeviceContext *dx = aContext.GetDeviceContext();
HDC srcdc = dx->GetDrawingSurface(aContext);
if (NULL != srcdc)
{
HBITMAP oldbits = ::SelectObject(srcdc, mHBitmap);
//if((aWidth == mBHead->biWidth) && (aHeight == mBHead->biHeight))
//BitBlt(the_hdc,aX,aY,aWidth,aHeight,mOptimizeDC,0,0,SRCCOPY);
if (!::StretchBlt(the_hdc, aX, aY, aWidth, aHeight, srcdc, 0, 0,
mBHead->biWidth, mBHead->biHeight, SRCCOPY))
error = ::GetLastError();
if (nsnull != oldbits)
::SelectObject(srcdc, oldbits);
}
NS_RELEASE(dx);
}
return PR_TRUE;
}
//------------------------------------------------------------
void nsImageWin::CompositeImage(nsIImage *aTheImage, nsPoint *aULLocation,nsBlendQuality aBlendQuality)
{
// call the correct sub routine for each blend
if ((mNumBytesPixel == 3) && (((nsImageWin *)aTheImage)->mNumBytesPixel == 3))
this->Comp24to24((nsImageWin*)aTheImage, aULLocation,aBlendQuality);
}
//------------------------------------------------------------
// lets build an alpha mask from this image
PRBool nsImageWin::SetAlphaMask(nsIImage *aTheMask)
{
PRInt32 num;
PRUint8 *srcbits;
if (aTheMask && (((nsImageWin*)aTheMask)->mNumBytesPixel == 1))
{
mLocation.x = 0;
mLocation.y = 0;
mAlphaDepth = 8;
mAlphaWidth = aTheMask->GetWidth();
mAlphaHeight = aTheMask->GetWidth();
num = mAlphaWidth*mAlphaHeight;
mARowBytes = aTheMask->GetLineStride();
mAlphaBits = new unsigned char[mARowBytes * mAlphaHeight];
srcbits = aTheMask->GetBits();
memcpy(mAlphaBits,srcbits,num);
return(PR_TRUE);
}
return(PR_FALSE);
}
//------------------------------------------------------------
PRBool nsImageWin::CalcAlphaMetrics(nsIImage *aTheImage,nsPoint *aULLocation,PRInt32 *aNumlines,
PRInt32 *aNumbytes,PRUint8 **aSImage,PRUint8 **aDImage,
PRUint8 **aMImage,PRInt32 *aSLSpan,PRInt32 *aDLSpan,PRInt32 *aMLSpan)
{
PRBool doalpha = PR_FALSE;
nsRect arect,srect,drect,irect;
PRInt32 startx,starty,x,y;
PRUint8 *alphabits;
if( IsOptimized() )
return doalpha;
alphabits = aTheImage->GetAlphaBits();
if(alphabits)
{
arect.SetRect(0,0,this->GetWidth(),this->GetHeight());
srect.SetRect(aTheImage->GetAlphaXLoc(),aTheImage->GetAlphaYLoc(),aTheImage->GetAlphaWidth(),aTheImage->GetAlphaHeight());
arect.IntersectRect(arect,srect);
}
else
{
arect.SetRect(0, 0, this->GetWidth(), this->GetHeight());
x = y = 0;
}
srect.SetRect(aULLocation->x, aULLocation->y, aTheImage->GetWidth(), aTheImage->GetHeight());
drect = arect;
if (irect.IntersectRect(srect, drect))
{
// calculate destination information
*aDLSpan = this->GetLineStride();
*aNumbytes = this->CalcBytesSpan(irect.width);
*aNumlines = irect.height;
startx = irect.x;
starty = this->GetHeight() - (irect.y + irect.height);
*aDImage = mImageBits + (starty * (*aDLSpan)) + (3 * startx);
// get the intersection relative to the source rectangle
srect.SetRect(0, 0, aTheImage->GetWidth(), aTheImage->GetHeight());
drect = irect;
drect.MoveBy(-aULLocation->x, -aULLocation->y);
drect.IntersectRect(drect,srect);
*aSLSpan = aTheImage->GetLineStride();
startx = drect.x;
starty = aTheImage->GetHeight() - (drect.y + drect.height);
*aSImage = aTheImage->GetBits() + (starty * (*aSLSpan)) + (3 * startx);
// 24 bit
doalpha = PR_TRUE;
if(alphabits)
{
*aMLSpan = aTheImage->GetAlphaLineStride();
*aMImage = alphabits;
}
else
{
aMLSpan = 0;
*aMImage = nsnull;
}
}
return doalpha;
}
//------------------------------------------------------------
// this routine has to flip the y, since the bits are in bottom scan
// line to top.
void nsImageWin::Comp24to24(nsImageWin *aTheImage,nsPoint *aULLocation,nsBlendQuality aBlendQuality)
{
nsRect arect,srect,drect,irect;
PRInt32 dlinespan,slinespan,mlinespan,numbytes,numlines;
PRUint8 *alphabits,*s1,*d1,*m1;
if( IsOptimized() )
return;
if(CalcAlphaMetrics(aTheImage,aULLocation,&numlines,&numbytes,&s1,&d1,&m1,&slinespan,&dlinespan,&mlinespan))
{
alphabits = aTheImage->GetAlphaBits();
if(alphabits)
{
numbytes/=3; // since the mask is only 8 bits, this routine wants number of pixels
Do24BlendWithMask(numlines,numbytes,s1,d1,m1,slinespan,dlinespan,mlinespan,aBlendQuality);
}
else
{
Do24Blend(128,numlines,numbytes,s1,d1,slinespan,dlinespan,aBlendQuality);
}
}
}
//------------------------------------------------------------
// This routine can not be fast enough
void
nsImageWin::Do24BlendWithMask(PRInt32 aNumlines,PRInt32 aNumbytes,PRUint8 *aSImage,PRUint8 *aDImage,PRUint8 *aMImage,PRInt32 aSLSpan,PRInt32 aDLSpan,PRInt32 aMLSpan,nsBlendQuality aBlendQuality)
{
PRUint8 *d1,*d2,*s1,*s2,*m1,*m2;
PRInt32 x,y;
PRUint32 val1,val2,temp1,numlines,xinc,yinc;
PRInt32 sspan,dspan,mspan;
sspan = aSLSpan;
dspan = aDLSpan;
mspan = aMLSpan;
// now go thru the image and blend (remember, its bottom upwards)
s1 = aSImage;
d1 = aDImage;
m1 = aMImage;
numlines = aNumlines;
xinc = 1;
yinc = 1;
for (y = 0; y < aNumlines; y++)
{
s2 = s1;
d2 = d1;
m2 = m1;
for(x=0;x<aNumbytes;x++)
{
val1 = (*m2);
val2 = 255-val1;
temp1 = (((*d2)*val1)+((*s2)*val2))>>8;
if(temp1>255)
temp1 = 255;
*d2 = (unsigned char)temp1;
d2++;
s2++;
temp1 = (((*d2)*val1)+((*s2)*val2))>>8;
if(temp1>255)
temp1 = 255;
*d2 = (unsigned char)temp1;
d2++;
s2++;
temp1 = (((*d2)*val1)+((*s2)*val2))>>8;
if(temp1>255)
temp1 = 255;
*d2 = (unsigned char)temp1;
d2++;
s2++;
m2++;
}
s1 += sspan;
d1 += dspan;
m1 += mspan;
}
}
//------------------------------------------------------------
// This routine can not be fast enough
void
nsImageWin::Do24Blend(PRUint8 aBlendVal,PRInt32 aNumlines,PRInt32 aNumbytes,PRUint8 *aSImage,PRUint8 *aDImage,PRInt32 aSLSpan,PRInt32 aDLSpan,nsBlendQuality aBlendQuality)
{
PRUint8 *d1,*d2,*s1,*s2;
PRInt32 x,y,val1,val2,temp1,numlines,xinc,yinc;;
// now go thru the image and blend (remember, its bottom upwards)
s1 = aSImage;
d1 = aDImage;
val1 = aBlendVal;
val2 = 255-val1;
numlines = aNumlines;
xinc = 1;
yinc = 1;
for(y = 0; y < aNumlines; y++)
{
s2 = s1;
d2 = d1;
for(x = 0; x < aNumbytes; x++)
{
temp1 = (((*d2)*val1)+((*s2)*val2))>>8;
if(temp1>255)
temp1 = 255;
*d2 = (unsigned char)temp1;
d2++;
s2++;
}
s1 += aSLSpan;
d1 += aDLSpan;
}
}
//------------------------------------------------------------
nsIImage*
nsImageWin::DuplicateImage()
{
PRInt32 num,i;
nsImageWin *theimage;
if( IsOptimized() )
return nsnull;
theimage = new nsImageWin();
NS_ADDREF(theimage);
// get the header and copy it
theimage->mBHead = (LPBITMAPINFOHEADER)new char[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * theimage->mNumPalleteColors];
num = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * theimage->mNumPalleteColors;
memcpy(theimage->mBHead,this->mBHead,num);
// set in compute metrics
theimage->mSizeImage = this->mSizeImage;
theimage->mRowBytes = this->mRowBytes;
theimage->mColorTable = (PRUint8 *)theimage->mBHead + sizeof(BITMAPINFOHEADER);
theimage->mNumBytesPixel = this->mNumBytesPixel;
theimage->mNumPalleteColors = this->mNumPalleteColors;
theimage->mAlphaDepth = this->mAlphaDepth;
theimage->mARowBytes = this->mARowBytes;
theimage->mAlphaWidth = this->mAlphaWidth;
theimage->mAlphaHeight = this->mAlphaHeight;
theimage->mLocation = this->mLocation;
theimage->mIsOptimized = this->mIsOptimized;
// set up the memory
num = sizeof(RGBQUAD) * mNumPalleteColors;
if(num>0)
memcpy(mColorTable,this->mColorTable,sizeof(RGBQUAD) * mNumPalleteColors);
// the bits of the image
if(theimage->mSizeImage>0)
{
theimage->mImageBits = new unsigned char[theimage->mSizeImage];
memcpy(theimage->mImageBits,this->mImageBits,theimage->mSizeImage);
}
else
theimage->mImageBits = nsnull;
// bits of the alpha mask
num = theimage->mAlphaWidth*theimage->mAlphaHeight;
if(num>0)
{
theimage->mAlphaBits = new unsigned char[num];
memcpy(theimage->mImageBits,this->mImageBits,theimage->mSizeImage);
}
else
theimage->mAlphaBits = nsnull;
theimage->mColorMap = new nsColorMap;
if (theimage->mColorMap != nsnull)
{
theimage->mColorMap->NumColors = theimage->mNumPalleteColors;
theimage->mColorMap->Index = new PRUint8[3 * theimage->mNumPalleteColors];
memset(theimage->mColorMap->Index, 0, sizeof(PRUint8) * (3 * theimage->mNumPalleteColors));
}
for(i = 0; i < theimage->mColorMap->NumColors; i++)
{
theimage->mColorMap->Index[(3 * i) + 2] = this->mColorMap->Index[(3 * i) + 2];
theimage->mColorMap->Index[(3 * i) + 1] = this->mColorMap->Index[(3 * i) + 1];
theimage->mColorMap->Index[(3 * i)] = this->mColorMap->Index[(3 * i)];
}
theimage->MakePalette();
theimage->mHBitmap = nsnull;
return (theimage);
}
//------------------------------------------------------------
PRBool nsImageWin::MakePalette()
{
// makes a logical palette (mHPalette) from the DIB's color table
// this palette will be selected and realized prior to drawing the DIB
if (mNumPalleteColors == 0)
return PR_FALSE;
if (mHPalette != nsnull)
::DeleteObject(mHPalette);
LPLOGPALETTE pLogPal = (LPLOGPALETTE) new char[2 * sizeof(WORD) + mNumPalleteColors * sizeof(PALETTEENTRY)];
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = mNumPalleteColors;
LPRGBQUAD pDibQuad = (LPRGBQUAD) mColorTable;
for (int i = 0; i < mNumPalleteColors; i++)
{
pLogPal->palPalEntry[i].peRed = pDibQuad->rgbRed;
pLogPal->palPalEntry[i].peGreen = pDibQuad->rgbGreen;
pLogPal->palPalEntry[i].peBlue = pDibQuad->rgbBlue;
pLogPal->palPalEntry[i].peFlags = 0;
pDibQuad++;
}
mHPalette = ::CreatePalette(pLogPal);
delete pLogPal;
return PR_TRUE;
}
//------------------------------------------------------------
PRBool nsImageWin :: SetSystemPalette(HDC* aHdc)
{
PRInt32 nsyscol, npal, nument;
// if the DIB doesn't have a color table, we can use the system palette
if (mNumPalleteColors != 0)
return PR_FALSE;
if (!::GetDeviceCaps(aHdc, RASTERCAPS) & RC_PALETTE)
return PR_FALSE;
nsyscol = ::GetDeviceCaps(aHdc, NUMCOLORS);
npal = ::GetDeviceCaps(aHdc, SIZEPALETTE);
nument = (npal == 0) ? nsyscol : npal;
LPLOGPALETTE pLogPal = (LPLOGPALETTE) new char[2 * sizeof(WORD) + nument * sizeof(PALETTEENTRY)];
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = nument;
::GetSystemPaletteEntries(aHdc, 0, nument, (LPPALETTEENTRY)((LPBYTE)pLogPal + 2 * sizeof(WORD)));
mHPalette = ::CreatePalette(pLogPal);
delete pLogPal;
return PR_TRUE;
}
//------------------------------------------------------------
// creates an optimized bitmap, or HBITMAP
nsresult nsImageWin :: Optimize(nsDrawingSurface aSurface)
{
return NS_OK; // TAKE THIS OUT
HDC the_hdc = (HDC)aSurface;
if ((the_hdc != NULL) && !IsOptimized() && (mSizeImage > 0))
{
mHBitmap = ::CreateDIBitmap(the_hdc, mBHead, CBM_INIT, mImageBits, (LPBITMAPINFO)mBHead, DIB_RGB_COLORS);
mIsOptimized = PR_TRUE;
CleanUp(PR_FALSE);
}
return NS_OK;
}
//------------------------------------------------------------
// figure out how big our palette needs to be
void nsImageWin :: ComputePaletteSize(PRIntn nBitCount)
{
switch (nBitCount)
{
case 8:
mNumPalleteColors = 256;
mNumBytesPixel = 1;
break;
case 24:
mNumPalleteColors = 0;
mNumBytesPixel = 3;
break;
default:
mNumPalleteColors = -1;
mNumBytesPixel = 0;
break;
}
}
//------------------------------------------------------------
PRInt32 nsImageWin :: CalcBytesSpan(PRUint32 aWidth)
{
PRInt32 spanbytes;
spanbytes = (aWidth * mBHead->biBitCount) >> 5;
if (((PRUint32)mBHead->biWidth * mBHead->biBitCount) & 0x1F)
spanbytes++;
spanbytes <<= 2;
return(spanbytes);
}
//------------------------------------------------------------
void nsImageWin :: ComputeMetrics()
{
mSizeImage = mBHead->biSizeImage;
if (mSizeImage == 0)
{
mRowBytes = CalcBytesSpan(mBHead->biWidth);
mSizeImage = mRowBytes * mBHead->biHeight; // no compression
}
// set the color table in the info header
mColorTable = (PRUint8 *)mBHead + sizeof(BITMAPINFOHEADER);
}
//------------------------------------------------------------
// clean up our memory
void nsImageWin :: CleanUp(PRBool aCleanUpAll)
{
// this only happens when we need to clean up everything
if (aCleanUpAll == PR_TRUE)
{
if (mAlphaBits != nsnull)
delete [] mAlphaBits;
if (mHBitmap != nsnull)
::DeleteObject(mHBitmap);
if(mBHead)
{
delete[] mBHead;
mBHead = nsnull;
}
mHBitmap = nsnull;
mAlphaBits = nsnull;
mIsOptimized = PR_FALSE;
if (mImageBits != nsnull)
{
delete [] mImageBits;
mImageBits = nsnull;
}
}
if (mHPalette != nsnull)
::DeleteObject(mHPalette);
// Should be an ISupports, so we can release
if (mColorMap != nsnull)
{
if (mColorMap->Index != nsnull)
delete [] mColorMap->Index;
delete mColorMap;
}
mColorTable = nsnull;
mNumPalleteColors = -1;
mNumBytesPixel = 0;
mSizeImage = 0;
mHPalette = nsnull;
mImageBits = nsnull;
mColorMap = nsnull;
}

View File

@@ -0,0 +1,205 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsImageWin_h___
#define nsImageWin_h___
#include <windows.h>
#include "nsIImage.h"
class nsImageWin : public nsIImage
{
public:
nsImageWin();
~nsImageWin();
NS_DECL_ISUPPORTS
/**
@see nsIImage.h
*/
virtual PRInt32 GetHeight() { return mBHead->biHeight; }
virtual PRInt32 GetWidth() { return mBHead->biWidth; }
virtual PRUint8* GetBits() { return mImageBits; }
virtual PRInt32 GetLineStride() {return mRowBytes; }
virtual PRBool Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface, PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight);
virtual PRBool Draw(nsIRenderingContext &aContext, nsDrawingSurface aSurface, PRInt32 aSX, PRInt32 aSY, PRInt32 aSWidth, PRInt32 aSHeight,
PRInt32 aDX, PRInt32 aDY, PRInt32 aDWidth, PRInt32 aDHeight);
virtual nsColorMap* GetColorMap() {return mColorMap;}
virtual void ImageUpdated(nsIDeviceContext *aContext, PRUint8 aFlags, nsRect *aUpdateRect);
virtual nsresult Init(PRInt32 aWidth, PRInt32 aHeight, PRInt32 aDepth, nsMaskRequirements aMaskRequirements);
virtual PRBool IsOptimized() { return mIsOptimized; }
virtual nsresult Optimize(nsDrawingSurface aSurface);
virtual PRUint8* GetAlphaBits() { return mAlphaBits; }
virtual PRInt32 GetAlphaWidth() { return mAlphaWidth;}
virtual PRInt32 GetAlphaHeight() {return mAlphaHeight;}
virtual PRInt32 GetAlphaXLoc() {return mLocation.x;}
virtual PRInt32 GetAlphaYLoc() {return mLocation.y;}
virtual PRInt32 GetAlphaLineStride(){ return mARowBytes; }
virtual void CompositeImage(nsIImage *aTheImage,nsPoint *aULLocation,nsBlendQuality aQuality);
virtual nsIImage* DuplicateImage();
/**
* Return the header size of the Device Independent Bitmap(DIB).
* @return size of header in bytes
*/
PRIntn GetSizeHeader(){return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * mNumPalleteColors;}
/**
* Return the image size of the Device Independent Bitmap(DIB).
* @return size of image in bytes
*/
PRIntn GetSizeImage(){ return mSizeImage; }
/**
* Make a palette for the DIB.
* @return true or false if the palette was created
*/
PRBool MakePalette();
/**
* Set the for this pixelmap to the system palette.
* @param aHdc is the DC to get the palette from to use
* @return true or false if the palette was set
*/
PRBool SetSystemPalette(HDC* aHdc);
/**
* Set the palette for an HDC.
* @param aHDC is the DC to set the palette to
* @param bBackround tells if the DC is in the background
* @return true or false if the palette was set
*/
PRUintn UsePalette(HDC* aHdc, PRBool bBackground = PR_FALSE);
/**
* Calculate the number of bytes spaned for this image for a given width
* @param aWidth is the width to calculate the number of bytes for
* @return the number of bytes in this span
*/
PRInt32 CalcBytesSpan(PRUint32 aWidth);
PRBool SetAlphaMask(nsIImage *aTheMask);
void MoveAlphaMask(PRInt32 aX, PRInt32 aY){mLocation.x=aX;mLocation.y=aY;}
private:
/**
* Blend two 24 bit image arrays using an 8 bit alpha mask
* @param aNumlines Number of lines to blend
* @param aNumberBytes Number of bytes per line to blend
* @param aSImage Pointer to beginning of the source bytes
* @param aDImage Pointer to beginning of the destination bytes
* @param aMImage Pointer to beginning of the mask bytes
* @param aSLSpan number of bytes per line for the source bytes
* @param aDLSpan number of bytes per line for the destination bytes
* @param aMLSpan number of bytes per line for the Mask bytes
* @param aBlendQuality The quality of this blend, this is for tweening if neccesary
*/
void Do24BlendWithMask(PRInt32 aNumlines,PRInt32 aNumbytes,PRUint8 *aSImage,PRUint8 *aDImage,
PRUint8 *aMImage,PRInt32 aSLSpan,PRInt32 aDLSpan,PRInt32 aMLSpan,nsBlendQuality aBlendQuality);
/**
* Blend two 24 bit image arrays using a passed in blend value
* @param aNumlines Number of lines to blend
* @param aNumberBytes Number of bytes per line to blend
* @param aSImage Pointer to beginning of the source bytes
* @param aDImage Pointer to beginning of the destination bytes
* @param aMImage Pointer to beginning of the mask bytes
* @param aSLSpan number of bytes per line for the source bytes
* @param aDLSpan number of bytes per line for the destination bytes
* @param aMLSpan number of bytes per line for the Mask bytes
* @param aBlendQuality The quality of this blend, this is for tweening if neccesary
*/
void Do24Blend(PRUint8 aBlendVal,PRInt32 aNumlines,PRInt32 aNumbytes,PRUint8 *aSImage,PRUint8 *aDImage,
PRInt32 aSLSpan,PRInt32 aDLSpan,nsBlendQuality aBlendQuality);
/**
* Calculate the information we need to do a blend
* @param aNumlines Number of lines to blend
* @param aNumberBytes Number of bytes per line to blend
* @param aSImage Pointer to beginning of the source bytes
* @param aDImage Pointer to beginning of the destination bytes
* @param aMImage Pointer to beginning of the mask bytes
* @param aSLSpan number of bytes per line for the source bytes
* @param aDLSpan number of bytes per line for the destination bytes
* @param aMLSpan number of bytes per line for the Mask bytes
*/
PRBool CalcAlphaMetrics(nsIImage *aTheImage,nsPoint *aULLocation,PRInt32 *aNumlines,
PRInt32 *aNumbytes,PRUint8 **aSImage,PRUint8 **aDImage,
PRUint8 **aMImage,PRInt32 *SLSpan,PRInt32 *aDLSpan,PRInt32 *aMLSpan);
/**
* Clean up the memory used nsImageWin.
* @param aCleanUpAll if True, all the memory used will be released otherwise just clean up the DIB memory
*/
void CleanUp(PRBool aCleanUpAll);
/**
* Calculate the amount of memory needed for the palette
* @param aBitCount is the number of bits per pixel
*/
void ComputePaletteSize(PRIntn aBitCount);
/**
* Composite a 24 bit image into another 24 bit image
* @param aTheImage The image to blend into this image
* @param aULLocation The upper left coordinate to place the passed in image
* @param aBlendQuality The quality of this blend, this is for tweening if neccesary
*/
void Comp24to24(nsImageWin *aTheImage,nsPoint *aULLocation,nsBlendQuality aBlendQuality);
/**
* Calculate the amount of memory needed for the initialization of the pixelmap
*/
void ComputeMetrics();
PRUint8 PaletteMatch(PRUint8 r, PRUint8 g, PRUint8 b);
PRInt8 mNumBytesPixel; // number of bytes per pixel
PRInt16 mNumPalleteColors; // either 8 or 0
PRInt32 mSizeImage; // number of bytes
PRInt32 mRowBytes; // number of bytes per row
PRUint8 *mColorTable; // color table for the bitmap
PRUint8 *mImageBits; // starting address of DIB bits
PRBool mIsOptimized; // Have we turned our DIB into a GDI?
nsColorMap *mColorMap; // Redundant with mColorTable, but necessary
// alpha layer members
PRUint8 *mAlphaBits; // alpha layer if we made one
PRInt8 mAlphaDepth; // alpha layer depth
PRInt16 mARowBytes;
PRInt16 mAlphaWidth; // alpha layer width
PRInt16 mAlphaHeight; // alpha layer height
nsPoint mLocation; // alpha mask location
PRInt8 mImageCache; // place to save off the old image for fast animation
// for Set/GetColorMap
HPALETTE mHPalette;
HBITMAP mHBitmap; // the GDI bitmap
LPBITMAPINFOHEADER mBHead; // BITMAPINFOHEADER
};
#endif

View File

@@ -0,0 +1,947 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsRenderingContextWin.h"
#include <math.h>
class GraphicsState
{
public:
GraphicsState();
GraphicsState(GraphicsState &aState);
~GraphicsState();
GraphicsState *mNext;
nsTransform2D mMatrix;
nsRect mLocalClip;
nsRect mGlobalClip;
HRGN mClipRegion;
nscolor mBrushColor;
HBRUSH mSolidBrush;
nsIFontMetrics *mFontMetrics;
HFONT mFont;
nscolor mPenColor;
HPEN mSolidPen;
};
GraphicsState :: GraphicsState()
{
mNext = nsnull;
mMatrix.SetToIdentity();
mLocalClip.x = mLocalClip.y = mLocalClip.width = mLocalClip.height = 0;
mGlobalClip = mLocalClip;
mClipRegion = NULL;
mBrushColor = NS_RGB(0, 0, 0);
mSolidBrush = NULL;
mFontMetrics = nsnull;
mFont = NULL;
mPenColor = NS_RGB(0, 0, 0);
mSolidPen = NULL;
}
GraphicsState :: GraphicsState(GraphicsState &aState) :
mMatrix(&aState.mMatrix),
mLocalClip(aState.mLocalClip),
mGlobalClip(aState.mGlobalClip)
{
mNext = &aState;
mClipRegion = NULL;
mBrushColor = aState.mBrushColor;
mSolidBrush = NULL;
mFontMetrics = nsnull;
mFont = NULL;
mPenColor = aState.mPenColor;
mSolidPen = NULL;
}
GraphicsState :: ~GraphicsState()
{
if (NULL != mClipRegion)
{
::DeleteObject(mClipRegion);
mClipRegion = NULL;
}
if (NULL != mSolidBrush)
{
::DeleteObject(mSolidBrush);
mSolidBrush = NULL;
}
//don't delete this because it lives in the font metrics
mFont = NULL;
if (NULL != mSolidPen)
{
::DeleteObject(mSolidPen);
mSolidPen = NULL;
}
}
static NS_DEFINE_IID(kRenderingContextIID, NS_IRENDERING_CONTEXT_IID);
nsRenderingContextWin :: nsRenderingContextWin()
{
NS_INIT_REFCNT();
mDC = NULL;
mMainDC = NULL;
mDCOwner = nsnull;
mFontMetrics = nsnull;
mFontCache = nsnull;
mOrigSolidBrush = NULL;
mBlackBrush = NULL;
mOrigFont = NULL;
mDefFont = NULL;
mOrigSolidPen = NULL;
mBlackPen = NULL;
mCurrBrushColor = NULL;
mCurrFontMetrics = nsnull;
mCurrPenColor = NULL;
mNullPen = NULL;
#ifdef NS_DEBUG
mInitialized = PR_FALSE;
#endif
mStateCache = new nsVoidArray();
//create an initial GraphicsState
PushState();
mP2T = 1.0f;
}
nsRenderingContextWin :: ~nsRenderingContextWin()
{
NS_IF_RELEASE(mContext);
NS_IF_RELEASE(mFontMetrics);
NS_IF_RELEASE(mFontCache);
//destroy the initial GraphicsState
PopState();
//cleanup the DC so that we can just destroy objects
//in the graphics state without worrying that we are
//ruining the dc
if (NULL != mDC)
{
if (NULL != mOrigSolidBrush)
{
::SelectObject(mDC, mOrigSolidBrush);
mOrigSolidBrush = NULL;
}
if (NULL != mOrigFont)
{
::SelectObject(mDC, mOrigFont);
mOrigFont = NULL;
}
if (NULL != mDefFont)
{
::DeleteObject(mDefFont);
mDefFont = NULL;
}
if (NULL != mOrigSolidPen)
{
::SelectObject(mDC, mOrigSolidPen);
mOrigSolidPen = NULL;
}
if (NULL != mCurrBrush)
::DeleteObject(mCurrBrush);
if ((NULL != mBlackBrush) && (mBlackBrush != mCurrBrush))
::DeleteObject(mBlackBrush);
mCurrBrush = NULL;
mBlackBrush = NULL;
//don't kill the font because the font cache/metrics owns it
mCurrFont = NULL;
if (NULL != mCurrPen)
::DeleteObject(mCurrPen);
if ((NULL != mBlackPen) && (mBlackPen != mCurrPen))
::DeleteObject(mBlackPen);
if ((NULL != mNullPen) && (mNullPen != mCurrPen))
::DeleteObject(mNullPen);
mCurrPen = NULL;
mBlackPen = NULL;
mNullPen = NULL;
}
if (nsnull != mStateCache)
{
PRInt32 cnt = mStateCache->Count();
while (--cnt >= 0)
{
GraphicsState *state = (GraphicsState *)mStateCache->ElementAt(cnt);
mStateCache->RemoveElementAt(cnt);
if (nsnull != state)
delete state;
}
delete mStateCache;
mStateCache = nsnull;
}
if (nsnull != mDCOwner)
{
//first try to get rid of a DC originally associated with the window
//but pushed over to a dest DC for offscreen rendering. if there is no
//rolled over DC, then the mDC is the one associated with the window.
if (nsnull != mMainDC)
ReleaseDC((HWND)mDCOwner->GetNativeData(NS_NATIVE_WINDOW), mMainDC);
else if (nsnull != mDC)
ReleaseDC((HWND)mDCOwner->GetNativeData(NS_NATIVE_WINDOW), mDC);
}
NS_IF_RELEASE(mDCOwner);
mTMatrix = nsnull;
mDC = NULL;
mMainDC = NULL;
}
NS_IMPL_QUERY_INTERFACE(nsRenderingContextWin, kRenderingContextIID)
NS_IMPL_ADDREF(nsRenderingContextWin)
NS_IMPL_RELEASE(nsRenderingContextWin)
nsresult nsRenderingContextWin :: Init(nsIDeviceContext* aContext,
nsIWidget *aWindow)
{
NS_PRECONDITION(PR_FALSE == mInitialized, "double init");
mContext = aContext;
NS_IF_ADDREF(mContext);
mDC = (HWND)aWindow->GetNativeData(NS_NATIVE_GRAPHIC);
mDCOwner = aWindow;
if (mDCOwner)
NS_ADDREF(mDCOwner);
return CommonInit();
}
nsresult nsRenderingContextWin :: Init(nsIDeviceContext* aContext,
nsDrawingSurface aSurface)
{
NS_PRECONDITION(PR_FALSE == mInitialized, "double init");
mContext = aContext;
NS_IF_ADDREF(mContext);
mDC = (HDC)aSurface;
mDCOwner = nsnull;
return CommonInit();
}
nsresult nsRenderingContextWin :: CommonInit(void)
{
mTMatrix->AddScale(mContext->GetAppUnitsToDevUnits(),
mContext->GetAppUnitsToDevUnits());
mP2T = mContext->GetDevUnitsToAppUnits();
mFontCache = mContext->GetFontCache();
#ifdef NS_DEBUG
mInitialized = PR_TRUE;
#endif
mBlackBrush = ::CreateSolidBrush(RGB(0, 0, 0));
mOrigSolidBrush = ::SelectObject(mDC, mBlackBrush);
mDefFont = ::CreateFont(12, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY, FF_ROMAN | VARIABLE_PITCH, "Times New Roman");
mOrigFont = ::SelectObject(mDC, mDefFont);
mBlackPen = ::CreatePen(PS_SOLID, 0, RGB(0, 0, 0));
mOrigSolidPen = ::SelectObject(mDC, mBlackPen);
mGammaTable = mContext->GetGammaTable();
return NS_OK;
}
nsresult nsRenderingContextWin :: SelectOffScreenDrawingSurface(nsDrawingSurface aSurface)
{
mMainDC = mDC;
mDC = (HDC)aSurface;
return NS_OK;
}
void nsRenderingContextWin :: Reset()
{
}
nsIDeviceContext * nsRenderingContextWin :: GetDeviceContext(void)
{
NS_IF_ADDREF(mContext);
return mContext;
}
void nsRenderingContextWin :: PushState()
{
PRInt32 cnt = mStateCache->Count();
if (cnt == 0)
{
if (nsnull == mStates)
mStates = new GraphicsState();
else
mStates = new GraphicsState(*mStates);
}
else
{
GraphicsState *state = (GraphicsState *)mStateCache->ElementAt(cnt - 1);
mStateCache->RemoveElementAt(cnt - 1);
state->mNext = mStates;
//clone state info
state->mMatrix = mStates->mMatrix;
state->mLocalClip = mStates->mLocalClip;
state->mGlobalClip = mStates->mGlobalClip;
state->mClipRegion = nsnull;
state->mBrushColor = mStates->mBrushColor;
state->mSolidBrush = nsnull;
state->mFontMetrics = mStates->mFontMetrics;
state->mFont = nsnull;
state->mPenColor = mStates->mPenColor;
state->mSolidPen = nsnull;
mStates = state;
}
mTMatrix = &mStates->mMatrix;
}
void nsRenderingContextWin :: PopState()
{
if (nsnull == mStates)
{
NS_ASSERTION(!(nsnull == mStates), "state underflow");
}
else
{
GraphicsState *oldstate = mStates;
mStates = mStates->mNext;
mStateCache->AppendElement(oldstate);
if (nsnull != mStates)
{
mTMatrix = &mStates->mMatrix;
GraphicsState *pstate;
if (NULL != oldstate->mClipRegion)
{
pstate = mStates;
//the clip rect has changed from state to state, so
//install the previous clip rect
while ((nsnull != pstate) && (NULL == pstate->mClipRegion))
pstate = pstate->mNext;
if ((nsnull != pstate) && (pstate->mGlobalClip != oldstate->mGlobalClip))
::SelectClipRgn(mDC, pstate->mClipRegion);
else
::SelectClipRgn(mDC, NULL);
//kill the clip region we are popping off the stack
::DeleteObject(oldstate->mClipRegion);
oldstate->mClipRegion = NULL;
}
oldstate->mSolidBrush = NULL;
oldstate->mFont = NULL;
oldstate->mSolidPen = NULL;
}
else
mTMatrix = nsnull;
}
}
PRBool nsRenderingContextWin :: IsVisibleRect(const nsRect& aRect)
{
return PR_TRUE;
}
void nsRenderingContextWin :: SetClipRect(const nsRect& aRect, PRBool aIntersect)
{
nsRect trect = aRect;
mStates->mLocalClip = aRect;
mTMatrix->TransformCoord(&trect.x, &trect.y,
&trect.width, &trect.height);
//should we combine the new rect with the previous?
if (aIntersect == PR_TRUE)
{
if (PR_FALSE == mStates->mGlobalClip.IntersectRect(mStates->mGlobalClip, trect))
{
mStates->mGlobalClip.x = mStates->mGlobalClip.y = mStates->mGlobalClip.width = mStates->mGlobalClip.height = 0;
}
}
else
mStates->mGlobalClip = trect;
if (NULL != mStates->mClipRegion)
::DeleteObject(mStates->mClipRegion);
mStates->mClipRegion = ::CreateRectRgn(mStates->mGlobalClip.x,
mStates->mGlobalClip.y,
mStates->mGlobalClip.XMost(),
mStates->mGlobalClip.YMost());
::SelectClipRgn(mDC, mStates->mClipRegion);
}
const nsRect& nsRenderingContextWin :: GetClipRect()
{
return mStates->mLocalClip;
}
void nsRenderingContextWin :: SetColor(nscolor aColor)
{
mCurrentColor = aColor;
mColor = RGB(mGammaTable[NS_GET_R(aColor)],
mGammaTable[NS_GET_G(aColor)],
mGammaTable[NS_GET_B(aColor)]);
}
nscolor nsRenderingContextWin :: GetColor() const
{
return mCurrentColor;
}
void nsRenderingContextWin :: SetFont(const nsFont& aFont)
{
NS_IF_RELEASE(mFontMetrics);
mFontMetrics = mFontCache->GetMetricsFor(aFont);
}
const nsFont& nsRenderingContextWin :: GetFont()
{
return mFontMetrics->GetFont();
}
nsIFontMetrics* nsRenderingContextWin :: GetFontMetrics()
{
return mFontMetrics;
}
// add the passed in translation to the current translation
void nsRenderingContextWin :: Translate(nscoord aX, nscoord aY)
{
mTMatrix->AddTranslation((float)aX,(float)aY);
}
// add the passed in scale to the current scale
void nsRenderingContextWin :: Scale(float aSx, float aSy)
{
mTMatrix->AddScale(aSx, aSy);
}
nsTransform2D * nsRenderingContextWin :: GetCurrentTransform()
{
return mTMatrix;
}
nsDrawingSurface nsRenderingContextWin :: CreateDrawingSurface(nsRect *aBounds)
{
HDC hDC = ::CreateCompatibleDC(mDC);
if (nsnull != aBounds)
{
HBITMAP hBits = ::CreateCompatibleBitmap(mDC, aBounds->width, aBounds->height);
::SelectObject(hDC, hBits);
}
else
{
HBITMAP hBits = ::CreateCompatibleBitmap(mDC, 2, 2);
::SelectObject(hDC, hBits);
}
return hDC;
}
void nsRenderingContextWin :: DestroyDrawingSurface(nsDrawingSurface aDS)
{
HDC hDC = (HDC)aDS;
HBITMAP hTempBits = ::CreateCompatibleBitmap(hDC, 2, 2);
HBITMAP hBits = ::SelectObject(hDC, hTempBits);
if (nsnull != hBits)
::DeleteObject(hBits);
::DeleteObject(hTempBits);
::DeleteDC(hDC);
}
void nsRenderingContextWin :: DrawLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1)
{
mTMatrix->TransformCoord(&aX0,&aY0);
mTMatrix->TransformCoord(&aX1,&aY1);
SetupSolidPen();
::MoveToEx(mDC, (int)(aX0), (int)(aY0), NULL);
::LineTo(mDC, (int)(aX1), (int)(aY1));
}
void nsRenderingContextWin :: DrawRect(const nsRect& aRect)
{
RECT nr;
nsRect tr;
tr = aRect;
mTMatrix->TransformCoord(&tr.x,&tr.y,&tr.width,&tr.height);
nr.left = tr.x;
nr.top = tr.y;
nr.right = tr.x+tr.width;
nr.bottom = tr.y+tr.height;
::FrameRect(mDC, &nr, SetupSolidBrush());
}
void nsRenderingContextWin :: DrawRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
{
RECT nr;
mTMatrix->TransformCoord(&aX,&aY,&aWidth,&aHeight);
nr.left = aX;
nr.top = aY;
nr.right = aX+aWidth;
nr.bottom = aY+aHeight;
::FrameRect(mDC, &nr, SetupSolidBrush());
}
void nsRenderingContextWin :: FillRect(const nsRect& aRect)
{
RECT nr;
nsRect tr;
tr = aRect;
mTMatrix->TransformCoord(&tr.x,&tr.y,&tr.width,&tr.height);
nr.left = tr.x;
nr.top = tr.y;
nr.right = tr.x+tr.width;
nr.bottom = tr.y+tr.height;
::FillRect(mDC, &nr, SetupSolidBrush());
}
void nsRenderingContextWin :: FillRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
{
RECT nr;
nsRect tr;
mTMatrix->TransformCoord(&aX,&aY,&aWidth,&aHeight);
nr.left = aX;
nr.top = aY;
nr.right = aX+aWidth;
nr.bottom = aY+aHeight;
::FillRect(mDC, &nr, SetupSolidBrush());
}
void nsRenderingContextWin::DrawPolygon(nsPoint aPoints[], PRInt32 aNumPoints)
{
// First transform nsPoint's into POINT's; perform coordinate space
// transformation at the same time
POINT pts[20];
POINT* pp0 = pts;
if (aNumPoints > 20)
pp0 = new POINT[aNumPoints];
POINT* pp = pp0;
const nsPoint* np = &aPoints[0];
for (PRInt32 i = 0; i < aNumPoints; i++, pp++, np++)
{
pp->x = np->x;
pp->y = np->y;
mTMatrix->TransformCoord((int*)&pp->x,(int*)&pp->y);
}
// Outline the polygon
int pfm = ::GetPolyFillMode(mDC);
::SetPolyFillMode(mDC, WINDING);
LOGBRUSH lb;
lb.lbStyle = BS_NULL;
lb.lbColor = 0;
lb.lbHatch = 0;
SetupSolidPen();
HBRUSH brush = ::CreateBrushIndirect(&lb);
HBRUSH oldBrush = ::SelectObject(mDC, brush);
::Polygon(mDC, pp0, int(aNumPoints));
::SelectObject(mDC, oldBrush);
::DeleteObject(brush);
::SetPolyFillMode(mDC, pfm);
// Release temporary storage if necessary
if (pp0 != pts)
delete pp0;
}
void nsRenderingContextWin::FillPolygon(nsPoint aPoints[], PRInt32 aNumPoints)
{
// First transform nsPoint's into POINT's; perform coordinate space
// transformation at the same time
POINT pts[20];
POINT* pp0 = pts;
if (aNumPoints > 20)
pp0 = new POINT[aNumPoints];
POINT* pp = pp0;
const nsPoint* np = &aPoints[0];
for (PRInt32 i = 0; i < aNumPoints; i++, pp++, np++)
{
pp->x = np->x;
pp->y = np->y;
mTMatrix->TransformCoord((int*)&pp->x,(int*)&pp->y);
}
// Fill the polygon
int pfm = ::GetPolyFillMode(mDC);
::SetPolyFillMode(mDC, WINDING);
SetupSolidBrush();
if (NULL == mNullPen)
mNullPen = ::CreatePen(PS_NULL, 0, 0);
HPEN oldPen = ::SelectObject(mDC, mNullPen);
::Polygon(mDC, pp0, int(aNumPoints));
::SelectObject(mDC, oldPen);
::SetPolyFillMode(mDC, pfm);
// Release temporary storage if necessary
if (pp0 != pts)
delete pp0;
}
void nsRenderingContextWin :: DrawEllipse(const nsRect& aRect)
{
DrawEllipse(aRect.x, aRect.y, aRect.width, aRect.height);
}
void nsRenderingContextWin :: DrawEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
{
mTMatrix->TransformCoord(&aX, &aY, &aWidth, &aHeight);
SetupSolidPen();
HBRUSH oldBrush = ::SelectObject(mDC, ::GetStockObject(NULL_BRUSH));
::Ellipse(mDC, aX, aY, aX + aWidth, aY + aHeight);
::SelectObject(mDC, oldBrush);
}
void nsRenderingContextWin :: FillEllipse(const nsRect& aRect)
{
FillEllipse(aRect.x, aRect.y, aRect.width, aRect.height);
}
void nsRenderingContextWin :: FillEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
{
mTMatrix->TransformCoord(&aX, &aY, &aWidth, &aHeight);
SetupSolidPen();
SetupSolidBrush();
::Ellipse(mDC, aX, aY, aX + aWidth, aY + aHeight);
}
void nsRenderingContextWin :: DrawArc(const nsRect& aRect,
float aStartAngle, float aEndAngle)
{
this->DrawArc(aRect.x,aRect.y,aRect.width,aRect.height,aStartAngle,aEndAngle);
}
void nsRenderingContextWin :: DrawArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
float aStartAngle, float aEndAngle)
{
PRInt32 quad1, quad2, sx, sy, ex, ey, cx, cy;
float anglerad, distance;
mTMatrix->TransformCoord(&aX, &aY, &aWidth, &aHeight);
SetupSolidPen();
SetupSolidBrush();
// figure out the the coordinates of the arc from the angle
distance = (float)sqrt((float)(aWidth * aWidth + aHeight * aHeight));
cx = aX + aWidth / 2;
cy = aY + aHeight / 2;
anglerad = (float)(aStartAngle / (180.0 / 3.14159265358979323846));
quad1 = (PRInt32)(aStartAngle / 90.0);
sx = (PRInt32)(distance * cos(anglerad) + cx);
sy = (PRInt32)(cy - distance * sin(anglerad));
anglerad = (float)(aEndAngle / (180.0 / 3.14159265358979323846));
quad2 = (PRInt32)(aEndAngle / 90.0);
ex = (PRInt32)(distance * cos(anglerad) + cx);
ey = (PRInt32)(cy - distance * sin(anglerad));
// this just makes it consitent, on windows 95 arc will always draw CC, nt this sets direction
::SetArcDirection(mDC, AD_COUNTERCLOCKWISE);
::Arc(mDC, aX, aY, aX + aWidth, aY + aHeight, sx, sy, ex, ey);
}
void nsRenderingContextWin :: FillArc(const nsRect& aRect,
float aStartAngle, float aEndAngle)
{
this->FillArc(aRect.x, aRect.y, aRect.width, aRect.height, aStartAngle, aEndAngle);
}
void nsRenderingContextWin :: FillArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
float aStartAngle, float aEndAngle)
{
PRInt32 quad1, quad2, sx, sy, ex, ey, cx, cy;
float anglerad, distance;
mTMatrix->TransformCoord(&aX, &aY, &aWidth, &aHeight);
SetupSolidPen();
SetupSolidBrush();
// figure out the the coordinates of the arc from the angle
distance = (float)sqrt((float)(aWidth * aWidth + aHeight * aHeight));
cx = aX + aWidth / 2;
cy = aY + aHeight / 2;
anglerad = (float)(aStartAngle / (180.0 / 3.14159265358979323846));
quad1 = (PRInt32)(aStartAngle / 90.0);
sx = (PRInt32)(distance * cos(anglerad) + cx);
sy = (PRInt32)(cy - distance * sin(anglerad));
anglerad = (float)(aEndAngle / (180.0 / 3.14159265358979323846));
quad2 = (PRInt32)(aEndAngle / 90.0);
ex = (PRInt32)(distance * cos(anglerad) + cx);
ey = (PRInt32)(cy - distance * sin(anglerad));
// this just makes it consitent, on windows 95 arc will always draw CC, nt this sets direction
::SetArcDirection(mDC, AD_COUNTERCLOCKWISE);
::Pie(mDC, aX, aY, aX + aWidth, aY + aHeight, sx, sy, ex, ey);
}
void nsRenderingContextWin :: DrawString(const char *aString, PRUint32 aLength,
nscoord aX, nscoord aY,
nscoord aWidth)
{
int oldBkMode = ::SetBkMode(mDC, TRANSPARENT);
int x,y;
SetupFont();
COLORREF oldColor = ::SetTextColor(mDC, mColor);
x = aX;
y = aY;
mTMatrix->TransformCoord(&x,&y);
::TextOut(mDC,x,y,aString,aLength);
if (mFontMetrics->GetFont().decorations & NS_FONT_DECORATION_OVERLINE)
DrawLine(aX, aY, aX + aWidth, aY);
::SetBkMode(mDC, oldBkMode);
::SetTextColor(mDC, oldColor);
}
void nsRenderingContextWin :: DrawString(const PRUnichar *aString, PRUint32 aLength,
nscoord aX, nscoord aY, nscoord aWidth)
{
int x,y;
int oldBkMode = ::SetBkMode(mDC, TRANSPARENT);
SetupFont();
COLORREF oldColor = ::SetTextColor(mDC, mColor);
x = aX;
y = aY;
mTMatrix->TransformCoord(&x,&y);
::TextOutW(mDC,x,y,aString,aLength);
if (mFontMetrics->GetFont().decorations & NS_FONT_DECORATION_OVERLINE)
DrawLine(aX, aY, aX + aWidth, aY);
::SetBkMode(mDC, oldBkMode);
::SetTextColor(mDC, oldColor);
}
void nsRenderingContextWin :: DrawString(const nsString& aString,
nscoord aX, nscoord aY, nscoord aWidth)
{
DrawString(aString.GetUnicode(), aString.Length(), aX, aY, aWidth);
}
void nsRenderingContextWin :: DrawImage(nsIImage *aImage, nscoord aX, nscoord aY)
{
NS_PRECONDITION(PR_TRUE == mInitialized, "!initialized");
nscoord width, height;
width = NS_TO_INT_ROUND(mP2T * aImage->GetWidth());
height = NS_TO_INT_ROUND(mP2T * aImage->GetHeight());
this->DrawImage(aImage, aX, aY, width, height);
}
void nsRenderingContextWin :: DrawImage(nsIImage *aImage, nscoord aX, nscoord aY,
nscoord aWidth, nscoord aHeight)
{
nsRect tr;
tr.x = aX;
tr.y = aY;
tr.width = aWidth;
tr.height = aHeight;
this->DrawImage(aImage, tr);
}
void nsRenderingContextWin :: DrawImage(nsIImage *aImage, const nsRect& aSRect, const nsRect& aDRect)
{
nsRect sr,dr;
sr = aSRect;
mTMatrix->TransformCoord(&sr.x, &sr.y, &sr.width, &sr.height);
dr = aDRect;
mTMatrix->TransformCoord(&dr.x, &dr.y, &dr.width, &dr.height);
((nsImageWin *)aImage)->Draw(*this, mDC, sr.x, sr.y, sr.width, sr.height, dr.x, dr.y, dr.width, dr.height);
}
void nsRenderingContextWin :: DrawImage(nsIImage *aImage, const nsRect& aRect)
{
nsRect tr;
tr = aRect;
mTMatrix->TransformCoord(&tr.x, &tr.y, &tr.width, &tr.height);
((nsImageWin *)aImage)->Draw(*this, mDC, tr.x, tr.y, tr.width, tr.height);
}
nsresult nsRenderingContextWin :: CopyOffScreenBits(nsRect &aBounds)
{
if ((nsnull != mDC) && (nsnull != mMainDC))
{
GraphicsState *pstate = mStates;
//look for a cliprect somewhere in the stack...
while ((nsnull != pstate) && (NULL == pstate->mClipRegion))
pstate = pstate->mNext;
if (nsnull != pstate)
::SelectClipRgn(mMainDC, pstate->mClipRegion);
else
::SelectClipRgn(mMainDC, NULL);
::BitBlt(mMainDC, 0, 0, aBounds.width, aBounds.height, mDC, 0, 0, SRCCOPY);
}
else
NS_ASSERTION(0, "attempt to blit with bad DCs");
return NS_OK;
}
static numpen = 0;
static numbrush = 0;
static numfont = 0;
HBRUSH nsRenderingContextWin :: SetupSolidBrush(void)
{
if ((mCurrentColor != mCurrBrushColor) || (NULL == mCurrBrush))
{
HBRUSH tbrush = ::CreateSolidBrush(mColor);
::SelectObject(mDC, tbrush);
if (NULL != mCurrBrush)
::DeleteObject(mCurrBrush);
mStates->mSolidBrush = mCurrBrush = tbrush;
mStates->mBrushColor = mCurrBrushColor = mCurrentColor;
//printf("brushes: %d\n", ++numbrush);
}
return mCurrBrush;
}
void nsRenderingContextWin :: SetupFont(void)
{
if ((mFontMetrics != mCurrFontMetrics) || (NULL == mCurrFontMetrics))
{
HFONT tfont = (HFONT)mFontMetrics->GetFontHandle();
::SelectObject(mDC, tfont);
mStates->mFont = mCurrFont = tfont;
mStates->mFontMetrics = mCurrFontMetrics = mFontMetrics;
//printf("fonts: %d\n", ++numfont);
}
}
HPEN nsRenderingContextWin :: SetupSolidPen(void)
{
if ((mCurrentColor != mCurrPenColor) || (NULL == mCurrPen))
{
HPEN tpen = ::CreatePen(PS_SOLID, 0, mColor);
::SelectObject(mDC, tpen);
if (NULL != mCurrPen)
::DeleteObject(mCurrPen);
mStates->mSolidPen = mCurrPen = tpen;
mStates->mPenColor = mCurrPenColor = mCurrentColor;
//printf("pens: %d\n", ++numpen);
}
return mCurrPen;
}

View File

@@ -0,0 +1,168 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef nsRenderingContextWin_h___
#define nsRenderingContextWin_h___
#include "nsIRenderingContext.h"
#include "nsUnitConversion.h"
#include "nsFont.h"
#include "nsIFontMetrics.h"
#include "nsPoint.h"
#include "nsString.h"
#include "nsCRT.h"
#include "nsTransform2D.h"
#include "nsIViewManager.h"
#include "nsIWidget.h"
#include "nsRect.h"
#include "nsIFontCache.h"
#include "nsImageWin.h"
#include "nsIDeviceContext.h"
#include "nsVoidArray.h"
class GraphicsState;
class nsRenderingContextWin : public nsIRenderingContext
{
public:
nsRenderingContextWin();
~nsRenderingContextWin();
void* operator new(size_t sz) {
void* rv = new char[sz];
nsCRT::zero(rv, sz);
return rv;
}
NS_DECL_ISUPPORTS
virtual nsresult Init(nsIDeviceContext* aContext, nsIWidget *aWindow);
virtual nsresult Init(nsIDeviceContext* aContext, nsDrawingSurface aSurface);
virtual void Reset();
virtual nsIDeviceContext * GetDeviceContext(void);
virtual nsresult SelectOffScreenDrawingSurface(nsDrawingSurface aSurface);
virtual void PushState();
virtual void PopState();
virtual PRBool IsVisibleRect(const nsRect& aRect);
virtual void SetClipRect(const nsRect& aRect, PRBool aIntersect);
virtual const nsRect& GetClipRect();
virtual void SetColor(nscolor aColor);
virtual nscolor GetColor() const;
virtual void SetFont(const nsFont& aFont);
virtual const nsFont& GetFont();
virtual nsIFontMetrics * GetFontMetrics();
virtual void Translate(nscoord aX, nscoord aY);
virtual void Scale(float aSx, float aSy);
virtual nsTransform2D * GetCurrentTransform();
virtual nsDrawingSurface CreateDrawingSurface(nsRect *aBounds);
virtual void DestroyDrawingSurface(nsDrawingSurface aDS);
virtual void DrawLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1);
virtual void DrawRect(const nsRect& aRect);
virtual void DrawRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
virtual void FillRect(const nsRect& aRect);
virtual void FillRect(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
virtual void DrawPolygon(nsPoint aPoints[], PRInt32 aNumPoints);
virtual void FillPolygon(nsPoint aPoints[], PRInt32 aNumPoints);
virtual void DrawEllipse(const nsRect& aRect);
virtual void DrawEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
virtual void FillEllipse(const nsRect& aRect);
virtual void FillEllipse(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
virtual void DrawArc(const nsRect& aRect,
float aStartAngle, float aEndAngle);
virtual void DrawArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
float aStartAngle, float aEndAngle);
virtual void FillArc(const nsRect& aRect,
float aStartAngle, float aEndAngle);
virtual void FillArc(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight,
float aStartAngle, float aEndAngle);
virtual void DrawString(const char *aString, PRUint32 aLength,
nscoord aX, nscoord aY,
nscoord aWidth);
virtual void DrawString(const PRUnichar *aString, PRUint32 aLength, nscoord aX, nscoord aY,
nscoord aWidth);
virtual void DrawString(const nsString& aString, nscoord aX, nscoord aY,
nscoord aWidth);
virtual void DrawImage(nsIImage *aImage, nscoord aX, nscoord aY);
virtual void DrawImage(nsIImage *aImage, nscoord aX, nscoord aY,
nscoord aWidth, nscoord aHeight);
virtual void DrawImage(nsIImage *aImage, const nsRect& aRect);
virtual void DrawImage(nsIImage *aImage, const nsRect& aSRect, const nsRect& aDRect);
virtual nsresult CopyOffScreenBits(nsRect &aBounds);
private:
nsresult CommonInit(void);
HBRUSH SetupSolidBrush(void);
HPEN SetupSolidPen(void);
void SetupFont(void);
protected:
nscolor mCurrentColor;
nsTransform2D *mTMatrix; // transform that all the graphics drawn here will obey
nsIFontMetrics *mFontMetrics;
nsIFontCache *mFontCache;
HDC mDC;
COLORREF mColor;
nsIWidget *mDCOwner;
// int mOldMapMode;
nsIDeviceContext *mContext;
float mP2T;
HDC mMainDC;
//default objects
HBRUSH mOrigSolidBrush;
HBRUSH mBlackBrush;
HFONT mOrigFont;
HFONT mDefFont;
HPEN mOrigSolidPen;
HPEN mBlackPen;
//state management
GraphicsState *mStates;
nsVoidArray *mStateCache;
nscolor mCurrBrushColor;
HBRUSH mCurrBrush;
nsIFontMetrics *mCurrFontMetrics;
HFONT mCurrFont;
nscolor mCurrPenColor;
HPEN mCurrPen;
HPEN mNullPen;
PRUint8 *mGammaTable;
#ifdef NS_DEBUG
PRBool mInitialized;
#endif
};
#endif /* nsRenderingContextWin_h___ */

View File

@@ -0,0 +1,32 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include <stdio.h>
#include "nsColor.h"
#include "nsColorNames.h"
int main(int argc, char** argv)
{
const nsColorNames::NameTableEntry* et = &nsColorNames::kNameTable[0];
for (int i = 0; i < COLOR_MAX; i++, et++) {
nscolor rgba = nsColorNames::kColors[i];
printf("%s: NS_RGB(%d,%d,%d,%d)\n", et->name,
NS_GET_R(rgba), NS_GET_G(rgba), NS_GET_B(rgba), NS_GET_A(rgba));
}
return 0;
}

View File

@@ -0,0 +1,63 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=../..
DIRS = btest
include $(DEPTH)/config/config.mk
CPPSRCS = \
DumpColors.cpp \
TestColorNames.cpp \
TestRect.cpp \
$(NULL)
INCLUDES+=-I../src -I$(PUBLIC)/raptor -I$(PUBLIC)/xpcom
DIRS =
OBJS = $(CPPSRCS:.cpp=.o)
EX_LIBS = \
$(DIST)/lib/libraptorgfx.a \
$(DIST)/lib/libraptorbase.a \
$(DIST)/lib/libxpcom.a \
$(DIST)/lib/libplc21.a \
$(DIST)/lib/libplds21.a \
$(DIST)/lib/libnspr21.a \
$(NULL)
PROGS = $(addprefix $(OBJDIR)/, $(CPPSRCS:.cpp=))
TARGETS = $(PROGS)
include $(DEPTH)/config/rules.mk
$(OBJDIR)/%.o: %.cpp
@$(MAKE_OBJDIR)
$(CCC) -o $@ $(CFLAGS) -c $*.cpp
$(PROGS):$(OBJDIR)/%: $(OBJDIR)/%.o $(EX_LIBS)
@$(MAKE_OBJDIR)
$(CCC) -o $@ $@.o $(LDFLAGS) $(EX_LIBS) $(OS_LIBS)
export::
install:: $(TARGETS)
$(INSTALL) $(PROGS) $(DIST)/bin

View File

@@ -0,0 +1,114 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include <stdio.h>
#include <string.h>
#include "nsColorNames.h"
#include "prprf.h"
static const char* kJunkNames[] = {
nsnull,
"",
"123",
"backgroundz",
"zzzzzz",
"#@$&@#*@*$@$#"
};
int main(int argc, char** argv)
{
PRInt32 id;
int rv = 0;
// First make sure we can find all of the tags that are supposed to
// be in the table. Futz with the case to make sure any case will
// work
const nsColorNames::NameTableEntry* et = &nsColorNames::kNameTable[0];
const nsColorNames::NameTableEntry* end = &nsColorNames::kNameTable[COLOR_MAX];
while (et < end) {
// Lookup color by name and make sure it has the right id
char tagName[100];
id = nsColorNames::LookupName(et->name);
if (id < 0) {
printf("bug: can't find '%s'\n", et->name);
rv = -1;
}
if (et->id != id) {
printf("bug: name='%s' et->id=%d id=%d\n", et->name, et->id, id);
rv = -1;
}
// fiddle with the case to make sure we can still find it
strcpy(tagName, et->name);
tagName[0] = tagName[0] - 32;
id = nsColorNames::LookupName(tagName);
if (id < 0) {
printf("bug: can't find '%s'\n", tagName);
rv = -1;
}
if (et->id != id) {
printf("bug: name='%s' et->id=%d id=%d\n", et->name, et->id, id);
rv = -1;
}
// Check that color lookup by name gets the right rgb value
nscolor rgb;
if (!NS_ColorNameToRGB(et->name, &rgb)) {
printf("bug: name='%s' didn't NS_ColorNameToRGB\n", et->name);
rv = -1;
}
if (nsColorNames::kColors[et->id] != rgb) {
printf("bug: name='%s' ColorNameToRGB=%x kColors[%d]=%x\n",
et->name, rgb, nsColorNames::kColors[et->id]);
rv = -1;
}
// Check that parsing an RGB value in hex gets the right values
PRUint8 r = NS_GET_R(rgb);
PRUint8 g = NS_GET_G(rgb);
PRUint8 b = NS_GET_B(rgb);
char cbuf[50];
PR_snprintf(cbuf, sizeof(cbuf), "#%02x%02x%02x", r, g, b);
nscolor hexrgb;
if (!NS_HexToRGB(cbuf, &hexrgb)) {
printf("bug: hex conversion to color of '%s' failed\n", cbuf);
rv = -1;
}
if (!NS_HexToRGB(cbuf + 1, &hexrgb)) {
printf("bug: hex conversion to color of '%s' failed\n", cbuf);
rv = -1;
}
if (hexrgb != rgb) {
printf("bug: rgb=%x hexrgb=%x\n", rgb, hexrgb);
rv = -1;
}
et++;
}
// Now make sure we don't find some garbage
for (int i = 0; i < sizeof(kJunkNames) / sizeof(const char*); i++) {
const char* tag = kJunkNames[i];
id = nsColorNames::LookupName(tag);
if (id >= 0) {
printf("bug: found '%s'\n", tag ? tag : "(null)");
rv = -1;
}
}
return rv;
}

View File

@@ -0,0 +1,431 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsRect.h"
#include <stdio.h>
#ifdef XP_PC
#include <windows.h>
#endif
static PRBool
TestConstructors()
{
// Create a rectangle
nsRect rect1(10, 20, 30, 40);
// Make sure the rectangle was properly initialized
if ((rect1.x != 10) || (rect1.y != 20) ||
(rect1.width != 30) || (rect1.height != 40)) {
printf("rect initialization failed!\n");
return PR_FALSE;
}
// Create a second rect using the copy constructor
nsRect rect2(rect1);
// Make sure the rectangle was properly initialized
if ((rect2.x != rect1.x) || (rect2.y != rect1.y) ||
(rect2.width != rect1.width) || (rect2.height != rect1.height)) {
printf("rect copy constructor failed!\n");
return PR_FALSE;
}
return PR_TRUE;
}
static PRBool
TestEqualityOperator()
{
nsRect rect1(10, 20, 30, 40);
nsRect rect2(rect1);
// Test the equality operator
if (!(rect1 == rect2)) {
printf("rect equality operator failed!\n");
return PR_FALSE;
}
// Test the inequality operator
if (rect1 != rect2) {
printf("rect inequality operator failed!\n");
return PR_FALSE;
}
// Make sure that two empty rects are equal
rect1.Empty();
rect2.Empty();
if (!(rect1 == rect2)) {
printf("rect equality operator failed for empty rects!\n");
return PR_FALSE;
}
return PR_TRUE;
}
static PRBool
TestContainment()
{
nsRect rect1(10, 10, 50, 50);
// Test the point containment methods
//
// Basic test of a point in the middle of the rect
if (!rect1.Contains(rect1.x + rect1.width/2, rect1.y + rect1.height/2)) {
printf("point containment test #1 failed!\n");
return PR_FALSE;
}
// Test against a point at the left/top edges
if (!rect1.Contains(rect1.x, rect1.y)) {
printf("point containment test #2 failed!\n");
return PR_FALSE;
}
// Test against a point at the right/bottom extents
if (rect1.Contains(rect1.XMost(), rect1.YMost())) {
printf("point containment test #3 failed!\n");
return PR_FALSE;
}
// Test the rect containment methods
//
nsRect rect2(rect1);
// Test against a rect that's the same as rect1
if (!rect1.Contains(rect2)) {
printf("rect containment test #1 failed!\n");
return PR_FALSE;
}
// Test against a rect whose left edge (only) is outside of rect1
rect2.x--;
if (rect1.Contains(rect2)) {
printf("rect containment test #2 failed!\n");
return PR_FALSE;
}
rect2.x++;
// Test against a rect whose top edge (only) is outside of rect1
rect2.y--;
if (rect1.Contains(rect2)) {
printf("rect containment test #3 failed!\n");
return PR_FALSE;
}
rect2.y++;
// Test against a rect whose right edge (only) is outside of rect1
rect2.x++;
if (rect1.Contains(rect2)) {
printf("rect containment test #2 failed!\n");
return PR_FALSE;
}
rect2.x--;
// Test against a rect whose bottom edge (only) is outside of rect1
rect2.y++;
if (rect1.Contains(rect2)) {
printf("rect containment test #3 failed!\n");
return PR_FALSE;
}
rect2.y--;
return PR_TRUE;
}
// Test the method that returns a boolean result but doesn't return a
// a rectangle
static PRBool
TestIntersects()
{
nsRect rect1(10, 10, 50, 50);
nsRect rect2(rect1);
// Test against a rect that's the same as rect1
if (!rect1.Intersects(rect2)) {
printf("rect intersects test #1 failed!\n");
return PR_FALSE;
}
// Test against a rect that's enclosed by rect1
rect2.Deflate(1, 1);
if (!rect1.Contains(rect2) || !rect1.Intersects(rect2)) {
printf("rect intersects test #2 failed!\n");
return PR_FALSE;
}
rect2.Inflate(1, 1);
// Make sure inflate and deflate worked correctly
if (rect1 != rect2) {
printf("rect inflate or deflate failed!\n");
return PR_FALSE;
}
// Test against a rect that overlaps the left edge of rect1
rect2.x--;
if (!rect1.Intersects(rect2)) {
printf("rect containment test #3 failed!\n");
return PR_FALSE;
}
rect2.x++;
// Test against a rect that's outside of rect1 on the left
rect2.x -= rect2.width;
if (rect1.Intersects(rect2)) {
printf("rect containment test #4 failed!\n");
return PR_FALSE;
}
rect2.x += rect2.width;
// Test against a rect that overlaps the top edge of rect1
rect2.y--;
if (!rect1.Intersects(rect2)) {
printf("rect containment test #5 failed!\n");
return PR_FALSE;
}
rect2.y++;
// Test against a rect that's outside of rect1 on the top
rect2.y -= rect2.height;
if (rect1.Intersects(rect2)) {
printf("rect containment test #6 failed!\n");
return PR_FALSE;
}
rect2.y += rect2.height;
// Test against a rect that overlaps the right edge of rect1
rect2.x++;
if (!rect1.Intersects(rect2)) {
printf("rect containment test #7 failed!\n");
return PR_FALSE;
}
rect2.x--;
// Test against a rect that's outside of rect1 on the right
rect2.x += rect2.width;
if (rect1.Intersects(rect2)) {
printf("rect containment test #8 failed!\n");
return PR_FALSE;
}
rect2.x -= rect2.width;
// Test against a rect that overlaps the bottom edge of rect1
rect2.y++;
if (!rect1.Intersects(rect2)) {
printf("rect containment test #9 failed!\n");
return PR_FALSE;
}
rect2.y--;
// Test against a rect that's outside of rect1 on the bottom
rect2.y += rect2.height;
if (rect1.Intersects(rect2)) {
printf("rect containment test #10 failed!\n");
return PR_FALSE;
}
rect2.y -= rect2.height;
return PR_TRUE;
}
// Test the method that returns a boolean result and an intersection rect
static PRBool
TestIntersection()
{
nsRect rect1(10, 10, 50, 50);
nsRect rect2(rect1);
nsRect dest;
// Test against a rect that's the same as rect1
if (!dest.IntersectRect(rect1, rect2) || (dest != rect1)) {
printf("rect intersection test #1 failed!\n");
return PR_FALSE;
}
// Test against a rect that's enclosed by rect1
rect2.Deflate(1, 1);
if (!dest.IntersectRect(rect1, rect2) || (dest != rect2)) {
printf("rect intersection test #2 failed!\n");
return PR_FALSE;
}
rect2.Inflate(1, 1);
// Test against a rect that overlaps the left edge of rect1
rect2.x--;
if (!dest.IntersectRect(rect1, rect2) ||
(dest != nsRect(rect1.x, rect1.y, rect1.width - 1, rect1.height))) {
printf("rect intersection test #3 failed!\n");
return PR_FALSE;
}
rect2.x++;
// Test against a rect that's outside of rect1 on the left
rect2.x -= rect2.width;
if (dest.IntersectRect(rect1, rect2)) {
printf("rect intersection test #4 failed!\n");
return PR_FALSE;
}
// Make sure an empty rect is returned
if (!dest.IsEmpty()) {
printf("rect intersection test #4 no empty rect!\n");
return PR_FALSE;
}
rect2.x += rect2.width;
// Test against a rect that overlaps the top edge of rect1
rect2.y--;
if (!dest.IntersectRect(rect1, rect2) ||
(dest != nsRect(rect1.x, rect1.y, rect1.width, rect1.height - 1))) {
printf("rect intersection test #5 failed!\n");
return PR_FALSE;
}
rect2.y++;
// Test against a rect that's outside of rect1 on the top
rect2.y -= rect2.height;
if (dest.IntersectRect(rect1, rect2)) {
printf("rect intersection test #6 failed!\n");
return PR_FALSE;
}
// Make sure an empty rect is returned
if (!dest.IsEmpty()) {
printf("rect intersection test #6 no empty rect!\n");
return PR_FALSE;
}
rect2.y += rect2.height;
// Test against a rect that overlaps the right edge of rect1
rect2.x++;
if (!dest.IntersectRect(rect1, rect2) ||
(dest != nsRect(rect1.x + 1, rect1.y, rect1.width - 1, rect1.height))) {
printf("rect intersection test #7 failed!\n");
return PR_FALSE;
}
rect2.x--;
// Test against a rect that's outside of rect1 on the right
rect2.x += rect2.width;
if (dest.IntersectRect(rect1, rect2)) {
printf("rect intersection test #8 failed!\n");
return PR_FALSE;
}
// Make sure an empty rect is returned
if (!dest.IsEmpty()) {
printf("rect intersection test #8 no empty rect!\n");
return PR_FALSE;
}
rect2.x -= rect2.width;
// Test against a rect that overlaps the bottom edge of rect1
rect2.y++;
if (!dest.IntersectRect(rect1, rect2) ||
(dest != nsRect(rect1.x, rect1.y + 1, rect1.width, rect1.height - 1))) {
printf("rect intersection test #9 failed!\n");
return PR_FALSE;
}
rect2.y--;
// Test against a rect that's outside of rect1 on the bottom
rect2.y += rect2.height;
if (dest.IntersectRect(rect1, rect2)) {
printf("rect intersection test #10 failed!\n");
return PR_FALSE;
}
// Make sure an empty rect is returned
if (!dest.IsEmpty()) {
printf("rect intersection test #10 no empty rect!\n");
return PR_FALSE;
}
rect2.y -= rect2.height;
return PR_TRUE;
}
static PRBool
TestUnion()
{
nsRect rect1;
nsRect rect2(10, 10, 50, 50);
nsRect dest;
// Check the case where the receiver is an empty rect
rect1.Empty();
if (!dest.UnionRect(rect1, rect2) || (dest != rect2)) {
printf("rect union test #1 failed!\n");
return PR_FALSE;
}
// Check the case where the source rect is an empty rect
rect1 = rect2;
rect2.Empty();
if (!dest.UnionRect(rect1, rect2) || (dest != rect1)) {
printf("rect union test #2 failed!\n");
return PR_FALSE;
}
// Test the case where both rects are empty. This should fail
rect1.Empty();
rect2.Empty();
if (dest.UnionRect(rect1, rect2)) {
printf("rect union test #3 failed!\n");
return PR_FALSE;
}
// Test union case where the two rects don't overlap at all
rect1.SetRect(10, 10, 50, 50);
rect2.SetRect(100, 100, 50, 50);
if (!dest.UnionRect(rect1, rect2) ||
(dest != nsRect(rect1.x, rect1.y, rect2.XMost() - rect1.x, rect2.YMost() - rect1.y))) {
printf("rect union test #4 failed!\n");
return PR_FALSE;
}
// Test union case where the two rects overlap
rect1.SetRect(30, 30, 50, 50);
rect2.SetRect(10, 10, 50, 50);
if (!dest.UnionRect(rect1, rect2) ||
(dest != nsRect(rect2.x, rect2.y, rect1.XMost() - rect2.x, rect1.YMost() - rect2.y))) {
printf("rect union test #5 failed!\n");
return PR_FALSE;
}
return PR_TRUE;
}
int main(int argc, char** argv)
{
if (!TestConstructors())
return -1;
if (!TestEqualityOperator())
return -1;
if (!TestContainment())
return -1;
if (!TestIntersects())
return -1;
if (!TestIntersection())
return -1;
if (!TestUnion())
return -1;
return 0;
}

View File

@@ -0,0 +1,982 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
//we need openfilename stuff... MMP
#ifdef WIN32_LEAN_AND_MEAN
#undef WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include "prtypes.h"
#include <stdio.h>
#include "resources.h"
#include "nsIImageManager.h"
#include "nsIImageGroup.h"
#include "nsIImageRequest.h"
#include "nsIImageObserver.h"
#include "nsIRenderingContext.h"
#include "nsIImage.h"
#include "nsIWidget.h"
#include "nsGUIEvent.h"
#include "nsRect.h"
#include "nsWidgetsCID.h"
#include "nsGfxCIID.h"
#include "nsFont.h"
#include <windows.h>
static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID);
static NS_DEFINE_IID(kIImageObserverIID, NS_IIMAGEREQUESTOBSERVER_IID);
static NS_DEFINE_IID(kCWindowIID, NS_WINDOW_CID);
static NS_DEFINE_IID(kCChildWindowIID, NS_CHILD_CID);
static NS_DEFINE_IID(kCScrollbarIID, NS_VERTSCROLLBAR_CID);
static char* class1Name = "ImageTest";
static HANDLE gInstance, gPrevInstance;
static nsIImageManager *gImageManager = nsnull;
static nsIImageGroup *gImageGroup = nsnull;
static nsIImageRequest *gImageReq = nsnull;
static HWND gHwnd;
static nsIWidget *gWindow = nsnull;
static nsIImage *gImage = nsnull;
static nsIImage *gBlendImage = nsnull;
static nsIImage *gMaskImage = nsnull;
static PRBool gInstalledColorMap = PR_FALSE;
static PRInt32 gXOff,gYOff,gTestNum;
extern void Compositetest(PRInt32 aTestNum,nsIImage *aImage,nsIImage *aBImage,nsIImage *aMImage, PRInt32 aX, PRInt32 aY);
extern PRInt32 speedtest(nsIImage *aTheImage,nsIRenderingContext *aSurface, PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight);
extern PRInt32 drawtest(nsIRenderingContext *aSurface);
extern PRInt32 filltest(nsIRenderingContext *aSurface);
extern PRInt32 arctest(nsIRenderingContext *aSurface);
extern PRBool IsImageLoaded();
//------------------------------------------------------------
class MyBlendObserver : public nsIImageRequestObserver
{
private:
nsIImage **mImage; // address of pointer to put info into
public:
MyBlendObserver(nsIImage **aImage);
~MyBlendObserver();
NS_DECL_ISUPPORTS
virtual void Notify(nsIImageRequest *aImageRequest,nsIImage *aImage,
nsImageNotification aNotificationType,
PRInt32 aParam1, PRInt32 aParam2,void *aParam3);
virtual void NotifyError(nsIImageRequest *aImageRequest,nsImageError aErrorType);
};
//------------------------------------------------------------
MyBlendObserver::MyBlendObserver(nsIImage **aImage)
{
mImage = aImage;
}
//------------------------------------------------------------
MyBlendObserver::~MyBlendObserver()
{
}
//------------------------------------------------------------
NS_IMPL_ISUPPORTS(MyBlendObserver, kIImageObserverIID)
void
MyBlendObserver::Notify(nsIImageRequest *aImageRequest,
nsIImage *aImage,
nsImageNotification aNotificationType,
PRInt32 aParam1, PRInt32 aParam2,
void *aParam3)
{
switch (aNotificationType)
{
case nsImageNotification_kDimensions:
break;
case nsImageNotification_kPixmapUpdate:
case nsImageNotification_kImageComplete:
case nsImageNotification_kFrameComplete:
{
if (*mImage == nsnull && aImage)
{
*mImage = aImage;
NS_ADDREF(aImage);
}
if ( gBlendImage && (aNotificationType == nsImageNotification_kImageComplete) )
{
nsColorMap *cmap = (*mImage)->GetColorMap();
nsRect *rect = (nsRect *)aParam3;
Compositetest(gTestNum,gImage,gBlendImage,gMaskImage,gXOff,gYOff);
}
}
break;
}
}
//------------------------------------------------------------
void
MyBlendObserver::NotifyError(nsIImageRequest *aImageRequest,
nsImageError aErrorType)
{
::MessageBox(NULL, "Blend Image loading error!",class1Name, MB_OK);
}
//------------------------------------------------------------
class MyObserver : public nsIImageRequestObserver
{
public:
MyObserver();
~MyObserver();
NS_DECL_ISUPPORTS
virtual void Notify(nsIImageRequest *aImageRequest,nsIImage *aImage,
nsImageNotification aNotificationType,
PRInt32 aParam1, PRInt32 aParam2,void *aParam3);
virtual void NotifyError(nsIImageRequest *aImageRequest,nsImageError aErrorType);
};
//------------------------------------------------------------
MyObserver::MyObserver()
{
}
//------------------------------------------------------------
MyObserver::~MyObserver()
{
}
//------------------------------------------------------------
NS_IMPL_ISUPPORTS(MyObserver, kIImageObserverIID)
void
MyObserver::Notify(nsIImageRequest *aImageRequest,
nsIImage *aImage,
nsImageNotification aNotificationType,
PRInt32 aParam1, PRInt32 aParam2,
void *aParam3)
{
switch (aNotificationType)
{
case nsImageNotification_kDimensions:
{
char buffer[40];
sprintf(buffer, "Image:%d x %d", aParam1, aParam2);
::SetWindowText(gHwnd, buffer);
}
break;
case nsImageNotification_kPixmapUpdate:
case nsImageNotification_kImageComplete:
case nsImageNotification_kFrameComplete:
{
if (gImage == nsnull && aImage)
{
gImage = aImage;
NS_ADDREF(aImage);
}
if (!gInstalledColorMap && gImage)
{
nsColorMap *cmap = gImage->GetColorMap();
if (cmap != nsnull && cmap->NumColors > 0)
{
gWindow->SetColorMap(cmap);
}
gInstalledColorMap = PR_TRUE;
}
nsRect *rect = (nsRect *)aParam3;
nsIRenderingContext *drawCtx = gWindow->GetRenderingContext();
if (gImage)
{
drawCtx->DrawImage(gImage, 0, 0, gImage->GetWidth(), gImage->GetHeight());
}
}
break;
}
}
//------------------------------------------------------------
void
MyObserver::NotifyError(nsIImageRequest *aImageRequest,
nsImageError aErrorType)
{
::MessageBox(NULL, "Image loading error!",class1Name, MB_OK);
}
//------------------------------------------------------------
// This tests the compositing for the image
void
Compositetest(PRInt32 aTestNum,nsIImage *aImage,nsIImage *aBImage,nsIImage *aMImage, PRInt32 aX, PRInt32 aY)
{
nsPoint *location;
PRUint32 min,seconds,milli,i,h,w;
nsBlendQuality quality=nsMedQual;
SYSTEMTIME thetime;
nsIRenderingContext *drawCtx = gWindow->GetRenderingContext();
nsIImage *theimage;
if(aTestNum == 1)
{
location = new nsPoint(aX,aY);
if(aMImage)
{
aBImage->SetAlphaMask(aMImage);
aBImage->MoveAlphaMask(rand() % aImage->GetWidth(),rand() % aImage->GetHeight());
}
if(aMImage == nsnull)
{
location->x = rand() % aImage->GetWidth();
location->y = rand() % aImage->GetHeight();
printf("\n Image Location is %d, %d\n", location->x,location->y);
}
aImage->CompositeImage(aBImage,location,quality);
}
// speed test
if(aTestNum == 2)
{
printf("\nSTARTING Blending TEST\n");
::GetSystemTime(&thetime);
min = thetime.wMinute;
seconds = thetime.wSecond;
milli = thetime.wMilliseconds;
location = new nsPoint(aX,aY);
w = gImage->GetWidth();
h = gImage->GetHeight();
if(aMImage)
{
aBImage->SetAlphaMask(aMImage);
for(i=0;i<200;i++)
{
aBImage->MoveAlphaMask(rand()%w,rand()%h);
theimage = aImage->DuplicateImage();
theimage->CompositeImage(aBImage,location,quality);
drawCtx->DrawImage(theimage, 0, 0, theimage->GetWidth(), theimage->GetHeight());
NS_RELEASE(theimage);
// non buffered
//aImage->CompositeImage(aBImage,location,quality);
//drawCtx->DrawImage(aImage, 0, 0, aImage->GetWidth(), aImage->GetHeight());
}
}
else
{
for(i=0;i<200;i++)
{
aBImage->MoveAlphaMask(rand()%w,rand()%h);
//theimage = aImage->DuplicateImage();
//theimage->CompositeImage(aBImage,location,quality);
//drawCtx->DrawImage(theimage, 0, 0, theimage->GetWidth(), theimage->GetHeight());
//NS_RELEASE(theimage);
// non buffered
aImage->CompositeImage(aBImage,location,quality);
drawCtx->DrawImage(aImage, 0, 0, aImage->GetWidth(), aImage->GetHeight());
}
}
::GetSystemTime(&thetime);
min = thetime.wMinute-min;
if(min>0)
min = min*60;
seconds = min+thetime.wSecond-seconds;
if(seconds>0)
seconds = (seconds*1000)+thetime.wMilliseconds;
else
seconds = thetime.wMilliseconds;
milli=seconds-milli;
printf("The composite Time was %lu Milliseconds\n",milli);
}
if(aTestNum == 3)
{
location = new nsPoint(aX,aY);
if(aMImage)
{
aBImage->SetAlphaMask(aMImage);
for(i=0;i<200;i++)
{
DWORD pos = ::GetMessagePos();
POINT cpos;
cpos.x = LOWORD(pos);
cpos.y = HIWORD(pos);
::ScreenToClient(gHwnd, &cpos);
aBImage->MoveAlphaMask(cpos.x,cpos.y);
theimage = aImage->DuplicateImage();
theimage->CompositeImage(aBImage,location,quality);
drawCtx->DrawImage(theimage, 0, 0, theimage->GetWidth(), theimage->GetHeight());
NS_RELEASE(theimage);
MSG msg;
if (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
else
for(i=0;i<200;i++)
{
aBImage->MoveAlphaMask(rand()%w,rand()%h);
theimage = aImage->DuplicateImage();
theimage->CompositeImage(aBImage,location,quality);
drawCtx->DrawImage(theimage, 0, 0, theimage->GetWidth(), theimage->GetHeight());
NS_RELEASE(theimage);
}
}
drawCtx->DrawImage(aImage, 0, 0, aImage->GetWidth(), aImage->GetHeight());
// we are finished with this
if (gBlendImage)
{
NS_RELEASE(gBlendImage);
gBlendImage = NULL;
}
}
//------------------------------------------------------------
// This tests the speed for the bliting,
PRInt32
speedtest(nsIImage *aTheImage,nsIRenderingContext *aSurface, PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight,PRBool aOptimize)
{
PRUint32 min,seconds,milli,i;
SYSTEMTIME thetime;
printf("\nSTARTING TIMING TEST\n");
::GetSystemTime(&thetime);
min = thetime.wMinute;
seconds = thetime.wSecond;
milli = thetime.wMilliseconds;
if(aOptimize==PR_TRUE)
aTheImage->Optimize(aSurface);
for(i=0;i<200;i++)
aSurface->DrawImage(aTheImage,aX,aY,aWidth,aHeight);
::GetSystemTime(&thetime);
min = thetime.wMinute-min;
if(min>0)
min = min*60;
seconds = min+thetime.wSecond-seconds;
if(seconds>0)
seconds = (seconds*1000)+thetime.wMilliseconds;
else
seconds = thetime.wMilliseconds;
milli=seconds-milli;
if(aOptimize==PR_TRUE)
printf("The Optimized Blitting Time was %lu Milliseconds\n",milli);
else
printf("The Non-Optimized Blitting Time was %lu Milliseconds\n",milli);
return(milli);
}
//------------------------------------------------------------
PRInt32
arctest(nsIRenderingContext *aSurface)
{
nsFont *font;
nscolor white,black;
font = new nsFont("Times", NS_FONT_STYLE_NORMAL,NS_FONT_VARIANT_NORMAL,NS_FONT_WEIGHT_BOLD,0,12);
aSurface->SetFont(*font);
// clear surface
NS_ColorNameToRGB("white", &white);
NS_ColorNameToRGB("red", &black);
aSurface->SetColor(white);
aSurface->FillRect(0,0,1000,1000);
aSurface->SetColor(black);
aSurface->DrawArc(20, 20,50,100,(float)0.0,(float)90.0);
aSurface->FillArc(70, 20,50,100,(float)0.0,(float)90.0);
aSurface->DrawArc(150, 20,50,100,(float)90.0,(float)0.0);
aSurface->DrawString("0 to 90\0",20,8,30);
aSurface->DrawString("Reverse (eg 90 to 0)\0",120,8,30);
aSurface->DrawArc(20, 140,100,50,(float)130.0,(float)180.0);
aSurface->FillArc(70, 140,100,50,(float)130.0,(float)180.0);
aSurface->DrawArc(150, 140,100,50,(float)180.0,(float)130.0);
aSurface->DrawString("130 to 180\0",20,130,30);
aSurface->DrawArc(20, 200,50,100,(float)170.0,(float)300.0);
aSurface->FillArc(70, 200,50,100,(float)170.0,(float)300.0);
aSurface->DrawArc(150, 200,50,100,(float)300.0,(float)170.0);
aSurface->DrawString("170 to 300\0",20,190,30);
return(30);
}
//------------------------------------------------------------
PRInt32
drawtest(nsIRenderingContext *aSurface)
{
nsFont *font;
nsPoint *pointlist;
nscolor white,black;
font = new nsFont("Times", NS_FONT_STYLE_NORMAL,NS_FONT_VARIANT_NORMAL,NS_FONT_WEIGHT_BOLD,0,12);
aSurface->SetFont(*font);
// clear surface
NS_ColorNameToRGB("white", &white);
NS_ColorNameToRGB("black", &black);
aSurface->SetColor(white);
aSurface->FillRect(0,0,1000,1000);
aSurface->SetColor(black);
aSurface->DrawRect(20, 20, 100, 100);
aSurface->DrawString("This is a Rectangle\0",20,5,30);
aSurface->DrawLine(0,0,300,400);
pointlist = new nsPoint[6];
pointlist[0].x = 150;pointlist[0].y = 150;
pointlist[1].x = 200;pointlist[1].y = 150;
pointlist[2].x = 190;pointlist[2].y = 170;
pointlist[3].x = 210;pointlist[3].y = 190;
pointlist[4].x = 175;pointlist[4].y = 175;
pointlist[5].x = 150;pointlist[5].y = 150;
aSurface->DrawPolygon(pointlist,6);
aSurface->DrawString("This is a closed Polygon\0",210,150,30);
delete [] pointlist;
#ifdef WINDOWSBROKEN
pointlist = new nsPoint[5];
pointlist[0].x = 200;pointlist[0].y = 200;
pointlist[1].x = 250;pointlist[1].y = 200;
pointlist[2].x = 240;pointlist[2].y = 220;
pointlist[3].x = 260;pointlist[3].y = 240;
pointlist[4].x = 225;pointlist[4].y = 225;
aSurface->DrawPolygon(pointlist,6);
aSurface->DrawString("This is an open Polygon\0",250,200,30);
delete [] pointlist;
#endif
aSurface->DrawEllipse(30, 150,50,100);
aSurface->DrawString("This is an Ellipse\0",30,140,30);
return(30);
}
//------------------------------------------------------------
PRInt32
filltest(nsIRenderingContext *aSurface)
{
nsFont *font;
nsPoint *pointlist;
nscolor white,black;
font = new nsFont("Times", NS_FONT_STYLE_NORMAL,NS_FONT_VARIANT_NORMAL,NS_FONT_WEIGHT_BOLD,0,12);
aSurface->SetFont(*font);
// clear surface
NS_ColorNameToRGB("white", &white);
NS_ColorNameToRGB("black", &black);
aSurface->SetColor(white);
aSurface->FillRect(0,0,1000,1000);
aSurface->SetColor(black);
aSurface->FillRect(20, 20, 100, 100);
aSurface->DrawString("This is a Rectangle\0",20,5,30);
pointlist = new nsPoint[6];
pointlist[0].x = 150;pointlist[0].y = 150;
pointlist[1].x = 200;pointlist[1].y = 150;
pointlist[2].x = 190;pointlist[2].y = 170;
pointlist[3].x = 210;pointlist[3].y = 190;
pointlist[4].x = 175;pointlist[4].y = 175;
pointlist[5].x = 150;pointlist[5].y = 150;
aSurface->FillPolygon(pointlist,6);
aSurface->DrawString("This is a closed Polygon\0",210,150,30);
delete [] pointlist;
#ifdef WINDOWSBROKEN
pointlist = new nsPoint[5];
pointlist[0].x = 200;pointlist[0].y = 200;
pointlist[1].x = 250;pointlist[1].y = 200;
pointlist[2].x = 240;pointlist[2].y = 220;
pointlist[3].x = 260;pointlist[3].y = 240;
pointlist[4].x = 225;pointlist[4].y = 225;
aSurface->FillPolygon(pointlist,6);
aSurface->DrawString("This is an open Polygon\0",250,200,30);
delete [] pointlist;
#endif
aSurface->FillEllipse(30, 150,50,100);
aSurface->DrawString("This is an Ellipse\0",30,140,30);
return(30);
}
//------------------------------------------------------------
nsEventStatus PR_CALLBACK
MyHandleEvent(nsGUIEvent *aEvent)
{
nsEventStatus result = nsEventStatus_eConsumeNoDefault;
switch(aEvent->message)
{
case NS_PAINT:
{
// paint the background
nsIRenderingContext *drawCtx = ((nsPaintEvent*)aEvent)->renderingContext;
drawCtx->SetColor(aEvent->widget->GetBackgroundColor());
drawCtx->FillRect(*(((nsPaintEvent*)aEvent)->rect));
if (gImage)
{
drawCtx->DrawImage(gImage, 0, 0, gImage->GetWidth(), gImage->GetHeight());
}
return nsEventStatus_eConsumeNoDefault;
}
break;
}
return nsEventStatus_eIgnore;
}
//------------------------------------------------------------
void
MyReleaseImages()
{
if (gImageReq)
{
NS_RELEASE(gImageReq);
gImageReq = NULL;
}
if (gImage)
{
NS_RELEASE(gImage);
gImage = NULL;
}
gInstalledColorMap = PR_FALSE;
}
//------------------------------------------------------------
void
MyInterrupt()
{
if (gImageGroup)
{
gImageGroup->Interrupt();
}
}
//------------------------------------------------------------
#define FILE_URL_PREFIX "file://"
void
MyLoadImage(char *aFileName,PRBool aGenLoad,nsIImage **aTheImage)
{
char fileURL[256];
char *str;
MyInterrupt();
if(aGenLoad!=PR_TRUE)
MyReleaseImages();
if (gImageGroup == NULL)
{
nsIRenderingContext *drawCtx = gWindow->GetRenderingContext();
if (NS_NewImageGroup(&gImageGroup) != NS_OK || gImageGroup->Init(drawCtx) != NS_OK)
{
::MessageBox(NULL, "Couldn't create image group",class1Name, MB_OK);
NS_RELEASE(drawCtx);
return;
}
NS_RELEASE(drawCtx);
}
strcpy(fileURL, FILE_URL_PREFIX);
strcpy(fileURL + strlen(FILE_URL_PREFIX), aFileName);
str = fileURL;
while ((str = strchr(str, '\\')) != NULL)
*str = '/';
nscolor white;
// set up which image gets loaded
if(aGenLoad == PR_TRUE)
{
MyBlendObserver *observer = new MyBlendObserver(aTheImage);
NS_ColorNameToRGB("white", &white);
gImageReq = gImageGroup->GetImage(fileURL,observer,white, 0, 0, 0);
}
else
{
MyObserver *observer = new MyObserver();
NS_ColorNameToRGB("white", &white);
gImageReq = gImageGroup->GetImage(fileURL,observer,white, 0, 0, 0);
}
if (gImageReq == NULL)
{
::MessageBox(NULL, "Couldn't create image request",class1Name, MB_OK);
}
}
//------------------------------------------------------------
PRBool
OpenFileDialog(char *aBuffer, int32 aBufLen)
{
BOOL result = FALSE;
OPENFILENAME ofn;
// *.js is the standard File Name on the Save/Open Dialog
::strcpy(aBuffer, "*.gif;*.png;*.jpg;*.jpeg");
// fill the OPENFILENAME sruct
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = gHwnd;
ofn.hInstance = gInstance;
ofn.lpstrFilter = "All Images (*.gif,*.png,*.jpg,*.jpeg)\0*.gif;*png;*.jpg;*.jpeg\0GIF Files (*.gif)\0*.gif\0PNG Files (*.png)\0*.png\0JPEG Files (*.jpg,*.jpeg)\0*.jpg;*.jpeg\0All Files\0*.*\0\0";
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 1; // the first one in lpstrFilter
ofn.lpstrFile = aBuffer; // contains the file path name on return
ofn.nMaxFile = aBufLen;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL; // use default
ofn.lpstrTitle = NULL; // use default
ofn.Flags = OFN_CREATEPROMPT | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt = "gif"; // default extension is .js
ofn.lCustData = NULL;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
// call the open file dialog or the save file dialog according to aIsOpenDialog
result = ::GetOpenFileName(&ofn);
return (PRBool)result;
}
//------------------------------------------------------------
PRBool
IsImageLoaded()
{
if(gImageGroup == NULL) // go get an image for the window
{
char szFile[256];
::MessageBox(NULL, "Need To Open an Image",NULL, MB_OK);
if (!OpenFileDialog(szFile, 256))
return PR_FALSE;
MyLoadImage(szFile,PR_FALSE,NULL);
}
return PR_TRUE;
}
//------------------------------------------------------------
long PASCAL
WndProc(HWND hWnd, UINT msg, WPARAM param, LPARAM lparam)
{
HMENU hMenu;
char szFile[256];
switch (msg)
{
case WM_COMMAND:
hMenu = GetMenu(hWnd);
switch (LOWORD(param))
{
case TIMER_OPEN:
{
if (!OpenFileDialog(szFile, 256))
return 0L;
MyLoadImage(szFile,PR_FALSE,NULL);
break;
}
case TIMER_EXIT:
::DestroyWindow(hWnd);
exit(0);
break;
case RDMSK:
if (gMaskImage!=nsnull)
{
NS_RELEASE(gMaskImage);
gMaskImage = nsnull;
}
if (OpenFileDialog(szFile, 256))
MyLoadImage(szFile,PR_TRUE,&gMaskImage);
break;
case COMPINT:
gTestNum = 3;
case COMPTST:
if(LOWORD(param) == COMPTST)
gTestNum = 1;
case COMPTSTSPEED:
if(LOWORD(param) == COMPTSTSPEED)
gTestNum = 2;
IsImageLoaded();
if(gImage)
{
if (gBlendImage!=nsnull)
{
NS_RELEASE(gBlendImage);
gBlendImage = nsnull;
}
gXOff = 100;
gYOff = 100;
if (OpenFileDialog(szFile, 256))
MyLoadImage(szFile,PR_TRUE,&gBlendImage);
}
break;
case BSTNOOPT:
case BSTOPT:
IsImageLoaded();
if(gImage)
{
PRBool opt;
nsIRenderingContext *drawCtx = gWindow->GetRenderingContext();
if(LOWORD(param) == BSTNOOPT)
opt = PR_FALSE;
else
opt = PR_TRUE;
speedtest(gImage,drawCtx, 0, 0, gImage->GetWidth(), gImage->GetHeight(),opt);
}
break;
case DRAWTEST:
if(gWindow)
{
nsIRenderingContext *drawCtx = gWindow->GetRenderingContext();
drawtest(drawCtx);
}
break;
case FILLTEST:
if(gWindow)
{
nsIRenderingContext *drawCtx = gWindow->GetRenderingContext();
filltest(drawCtx);
}
break;
case ARCTEST:
if(gWindow)
{
nsIRenderingContext *drawCtx = gWindow->GetRenderingContext();
arctest(drawCtx);
}
break;
default:
break;
}
break;
case WM_CREATE:
// Initialize image library
if (NS_NewImageManager(&gImageManager) != NS_OK||gImageManager->Init() != NS_OK)
{
::MessageBox(NULL, "Can't initialize the image library",class1Name, MB_OK);
}
gImageManager->SetCacheSize(1024*1024);
break;
/*case WM_MOUSEMOVE:
{
DWORD pos = ::GetMessagePos();
POINT cpos;
cpos.x = LOWORD(pos);
cpos.y = HIWORD(pos);
::ScreenToClient(hWnd, &cpos);
// Dothing(cpos.x, cpos.y);
}
break;*/
case WM_DESTROY:
MyInterrupt();
MyReleaseImages();
if (gImageGroup != nsnull)
{
NS_RELEASE(gImageGroup);
}
if (gImageManager != nsnull)
{
NS_RELEASE(gImageManager);
}
if (gBlendImage)
{
NS_RELEASE(gBlendImage);
gBlendImage = NULL;
}
PostQuitMessage(0);
break;
default:
break;
}
return DefWindowProc(hWnd, msg, param, lparam);
}
//------------------------------------------------------------
static HWND CreateTopLevel(const char* clazz, const char* title,int aWidth, int aHeight)
{
// Create a simple top level window
HWND window = ::CreateWindowEx(WS_EX_CLIENTEDGE,
clazz, title,
WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT,
aWidth, aHeight,
HWND_DESKTOP,
NULL,
gInstance,
NULL);
nsRect rect(0, 0, aWidth, aHeight);
nsresult rv = NSRepository::CreateInstance(kCChildWindowIID, NULL, kIWidgetIID, (void**)&gWindow);
if (NS_OK == rv)
{
gWindow->Create((nsNativeWindow)window, rect, MyHandleEvent, NULL);
}
::ShowWindow(window, SW_SHOW);
::UpdateWindow(window);
return window;
}
#define WIDGET_DLL "raptorwidget.dll"
#define GFXWIN_DLL "raptorgfxwin.dll"
//------------------------------------------------------------
int PASCAL
WinMain(HANDLE instance, HANDLE prevInstance, LPSTR cmdParam, int nCmdShow)
{
gInstance = instance;
NSRepository::RegisterFactory(kCWindowIID, WIDGET_DLL, PR_FALSE, PR_FALSE);
NSRepository::RegisterFactory(kCChildWindowIID, WIDGET_DLL, PR_FALSE, PR_FALSE);
NSRepository::RegisterFactory(kCScrollbarIID, WIDGET_DLL, PR_FALSE, PR_FALSE);
static NS_DEFINE_IID(kCRenderingContextIID, NS_RENDERING_CONTEXT_CID);
static NS_DEFINE_IID(kCDeviceContextIID, NS_DEVICE_CONTEXT_CID);
static NS_DEFINE_IID(kCFontMetricsIID, NS_FONT_METRICS_CID);
static NS_DEFINE_IID(kCImageIID, NS_IMAGE_CID);
NSRepository::RegisterFactory(kCRenderingContextIID, GFXWIN_DLL, PR_FALSE, PR_FALSE);
NSRepository::RegisterFactory(kCDeviceContextIID, GFXWIN_DLL, PR_FALSE, PR_FALSE);
NSRepository::RegisterFactory(kCFontMetricsIID, GFXWIN_DLL, PR_FALSE, PR_FALSE);
NSRepository::RegisterFactory(kCImageIID, GFXWIN_DLL, PR_FALSE, PR_FALSE);
if (!prevInstance) {
WNDCLASS wndClass;
wndClass.style = 0;
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = gInstance;
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
wndClass.lpszMenuName = class1Name;
wndClass.lpszClassName = class1Name;
RegisterClass(&wndClass);
}
// Create our first top level window
gHwnd = CreateTopLevel(class1Name, "Graphics tester", 620, 400);
// Process messages
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
//------------------------------------------------------------
void main(int argc, char **argv)
{
WinMain(GetModuleHandle(NULL), NULL, 0, SW_SHOW);
}

View File

@@ -0,0 +1,42 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "resources.h"
IMAGETEST MENU DISCARDABLE
{
POPUP "File"
{
MENUITEM "Open...", TIMER_OPEN
MENUITEM "Exit", TIMER_EXIT
}
POPUP "TEST"
{
MENUITEM "Read Mask", RDMSK
MENUITEM "Composit Interactive",COMPINT
MENUITEM "Composit Test", COMPTST
MENUITEM "Composite Speed", COMPTSTSPEED
MENUITEM "Blit Speed",BSTNOOPT
MENUITEM "Blit Speed, Optimzed.",BSTOPT
MENUITEM "Draw Test",DRAWTEST
MENUITEM "Fill Test",FILLTEST
MENUITEM "Arc Test",ARCTEST
}
}

View File

@@ -0,0 +1,62 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=..\..\..
MAKE_OBJ_TYPE = EXE
PROG0 = .\$(OBJDIR)\BitTest.exe
RESFILE = image.res
PROGRAMS = $(PROG0)
LINCS=-I$(XPDIST)\public\raptor -I$(XPDIST)\public\xpcom -I..\src
LLIBS= \
$(DIST)\lib\raptorbase.lib \
$(DIST)\lib\raptorgfx.lib \
$(DIST)\lib\xpcom32.lib \
$(LIBNSPR) \
$(DIST)\lib\libplc21.lib \
$(DIST)\lib\img3240.lib \
$(DIST)\lib\util.lib \
comdlg32.lib \
$(RESFILE)
include <$(DEPTH)\config\rules.mak>
install:: $(PROGRAMS)
$(MAKE_INSTALL) $(PROG0) $(DIST)\bin
clobber::
rm -f $(DIST)\bin\BitTest.exe
# Move this into config/obj.inc when it's allowed
.cpp{.\$(OBJDIR)\}.exe:
$(CC) @<<$(CFGFILE)
$(CFLAGS)
$(LCFLAGS)
$(LINCS)
$(LINCS_1)
$(INCS)
$(LLIBS)
$(OS_LIBS)
-Fd$(PBDFILE)
-Fe.\$(OBJDIR)\
-Fo.\$(OBJDIR)\
$(CURDIR)$(*B).cpp
<<
$(PROG0): $(OBJDIR) BitTest.cpp $(RESFILE)

View File

@@ -0,0 +1,31 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#define ID_MENUITEM40001 40001
#define ID_MENUITEM40002 40002
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40003
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -0,0 +1,35 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef resources_h___
#define resources_h___
#define TIMER_OPEN 40010
#define TIMER_EXIT 40011
#define BSTNOOPT 40012
#define BSTOPT 40013
#define DRAWTEST 40014
#define FILLTEST 40015
#define ARCTEST 40016
#define COMPTST 40017
#define COMPTSTSPEED 40018
#define RDMSK 40019
#define COMPINT 40020
#endif /* resources_h___ */

View File

@@ -0,0 +1,70 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=..\..
IGNORE_MANIFEST=1
DIRS = btest
MAKE_OBJ_TYPE = EXE
PROG1 = .\$(OBJDIR)\TestRect.exe
PROG2 = .\$(OBJDIR)\TestColorNames.exe
PROG3 = .\$(OBJDIR)\DumpColors.exe
PROGRAMS = $(PROG1) $(PROG2) $(PROG3)
LINCS=-I$(XPDIST)\public\raptor -I$(XPDIST)\public\xpcom -I..\src
LLIBS= \
$(DIST)\lib\raptorbase.lib \
$(DIST)\lib\raptorgfx.lib \
$(DIST)\lib\xpcom32.lib \
$(LIBNSPR) \
$(DIST)\lib\libplc21.lib
include <$(DEPTH)\config\rules.mak>
install:: $(PROGRAMS)
$(MAKE_INSTALL) $(PROG1) $(DIST)\bin
$(MAKE_INSTALL) $(PROG2) $(DIST)\bin
$(MAKE_INSTALL) $(PROG3) $(DIST)\bin
clobber::
rm -f $(DIST)\bin\TestRect.exe
rm -f $(DIST)\bin\TestColorNames.exe
rm -f $(DIST)\bin\DumpColors.exe
# Move this into config/obj.inc when it's allowed
.cpp{.\$(OBJDIR)\}.exe:
$(CC) @<<$(CFGFILE)
$(CFLAGS)
$(LCFLAGS)
$(LINCS)
$(LINCS_1)
$(INCS)
$(LLIBS)
$(OS_LIBS)
-Fd$(PBDFILE)
-Fe.\$(OBJDIR)\
-Fo.\$(OBJDIR)\
$(CURDIR)$(*B).cpp
<<
$(PROG1): $(OBJDIR) TestRect.cpp
$(PROG2): $(OBJDIR) TestColorNames.cpp
$(PROG3): $(OBJDIR) DumpColors.cpp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 B

View File

@@ -1,97 +0,0 @@
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# 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 the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Terry Weissman <terry@mozilla.org>
# Myk Melez <myk@mozilla.org>
############################################################################
# Module Initialization
############################################################################
use diagnostics;
use strict;
package Attachment;
# This module requires that its caller have said "require CGI.pl" to import
# relevant functions from that script and its companion globals.pl.
############################################################################
# Functions
############################################################################
sub query
{
# Retrieves and returns an array of attachment records for a given bug.
# This data should be given to attachment/list.atml in an
# "attachments" variable.
my ($bugid) = @_;
my $in_editbugs = &::UserInGroup("editbugs");
# Retrieve a list of attachments for this bug and write them into an array
# of hashes in which each hash represents a single attachment.
&::SendSQL("
SELECT attach_id, creation_ts, mimetype, description, ispatch,
isobsolete, submitter_id
FROM attachments WHERE bug_id = $bugid ORDER BY attach_id
");
my @attachments = ();
while (&::MoreSQLData()) {
my %a;
my $submitter_id;
($a{'attachid'}, $a{'date'}, $a{'contenttype'}, $a{'description'},
$a{'ispatch'}, $a{'isobsolete'}, $submitter_id) = &::FetchSQLData();
# Format the attachment's creation/modification date into a standard
# format (YYYY-MM-DD HH:MM)
if ($a{'date'} =~ /^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/) {
$a{'date'} = "$1-$2-$3 $4:$5";
}
# Retrieve a list of status flags that have been set on the attachment.
&::PushGlobalSQLState();
&::SendSQL("
SELECT name
FROM attachstatuses, attachstatusdefs
WHERE attach_id = $a{'attachid'}
AND attachstatuses.statusid = attachstatusdefs.id
ORDER BY sortkey
");
my @statuses = ();
while (&::MoreSQLData()) {
my ($status) = &::FetchSQLData();
push @statuses , $status;
}
$a{'statuses'} = \@statuses;
&::PopGlobalSQLState();
# We will display the edit link if the user can edit the attachment;
# ie the are the submitter, or they have canedit.
# Also show the link if the user is not logged in - in that cae,
# They'll be prompted later
$a{'canedit'} = ($::userid == 0 || $submitter_id == $::userid ||
$in_editbugs);
push @attachments, \%a;
}
return \@attachments;
}
1;

View File

@@ -1,547 +0,0 @@
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# 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 the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Dawn Endico <endico@mozilla.org>
# Terry Weissman <terry@mozilla.org>
# Chris Yeh <cyeh@bluemartini.com>
use diagnostics;
use strict;
use DBI;
use RelationSet;
use vars qw($unconfirmedstate $legal_keywords);
require "globals.pl";
require "CGI.pl";
package Bug;
use CGI::Carp qw(fatalsToBrowser);
my %ok_field;
for my $key (qw (bug_id product version rep_platform op_sys bug_status
resolution priority bug_severity component assigned_to
reporter bug_file_loc short_desc target_milestone
qa_contact status_whiteboard creation_ts groupset
delta_ts votes whoid usergroupset comment query error) ){
$ok_field{$key}++;
}
# create a new empty bug
#
sub new {
my $type = shift();
my %bug;
# create a ref to an empty hash and bless it
#
my $self = {%bug};
bless $self, $type;
# construct from a hash containing a bug's info
#
if ($#_ == 1) {
$self->initBug(@_);
} else {
confess("invalid number of arguments \($#_\)($_)");
}
# bless as a Bug
#
return $self;
}
# dump info about bug into hash unless user doesn't have permission
# user_id 0 is used when person is not logged in.
#
sub initBug {
my $self = shift();
my ($bug_id, $user_id) = (@_);
my $old_bug_id = $bug_id;
if ((! defined $bug_id) || (!$bug_id) || (!&::detaint_natural($bug_id))) {
# no bug number given
$self->{'bug_id'} = $old_bug_id;
$self->{'error'} = "InvalidBugId";
return $self;
}
# default userid 0, or get DBID if you used an email address
unless (defined $user_id) {
$user_id = 0;
}
else {
if ($user_id =~ /^\@/) {
$user_id = &::DBname_to_id($user_id);
}
}
&::ConnectToDatabase();
&::GetVersionTable();
# this verification should already have been done by caller
# my $loginok = quietly_check_login();
$self->{'whoid'} = $user_id;
&::SendSQL("SELECT groupset FROM profiles WHERE userid=$self->{'whoid'}");
my $usergroupset = &::FetchOneColumn();
if (!$usergroupset) { $usergroupset = '0' }
$self->{'usergroupset'} = $usergroupset;
# Check to see if we can see this bug
if (!&::CanSeeBug($bug_id, $user_id, $usergroupset)) {
# Permission denied to see bug
$self->{'bug_id'} = $old_bug_id;
$self->{'error'} = "PermissionDenied";
return $self;
}
my $query = "";
if ($::driver eq 'mysql') {
$query = "
select
bugs.bug_id, product, version, rep_platform, op_sys, bug_status,
resolution, priority, bug_severity, component, assigned_to, reporter,
bug_file_loc, short_desc, target_milestone, qa_contact,
status_whiteboard, date_format(creation_ts,'%Y-%m-%d %H:%i'),
groupset, delta_ts, sum(votes.count)
from bugs left join votes using(bug_id)
where bugs.bug_id = $bug_id
group by bugs.bug_id";
} elsif ($::driver eq 'Pg') {
$query = "
select
bugs.bug_id, product, version, rep_platform, op_sys, bug_status,
resolution, priority, bug_severity, component, assigned_to, reporter,
bug_file_loc, short_desc, target_milestone, qa_contact,
status_whiteboard, creation_ts,
groupset, delta_ts, sum(votes.count)
from bugs left join votes using(bug_id)
where bugs.bug_id = $bug_id
and (bugs.groupset & int8($usergroupset)) = bugs.groupset
group by bugs.bug_id, product, version, rep_platform, op_sys, bug_status,
resolution, priority, bug_severity, component, assigned_to, reporter,
bug_file_loc, short_desc, target_milestone, qa_contact, status_whiteboard,
creation_ts, groupset, delta_ts";
}
&::SendSQL($query);
my @row;
if (@row = &::FetchSQLData()) {
my $count = 0;
my %fields;
foreach my $field ("bug_id", "product", "version", "rep_platform",
"op_sys", "bug_status", "resolution", "priority",
"bug_severity", "component", "assigned_to", "reporter",
"bug_file_loc", "short_desc", "target_milestone",
"qa_contact", "status_whiteboard", "creation_ts",
"groupset", "delta_ts", "votes") {
$fields{$field} = shift @row;
if ($fields{$field}) {
$self->{$field} = $fields{$field};
}
$count++;
}
} else {
&::SendSQL("select groupset from bugs where bug_id = $bug_id");
if (@row = &::FetchSQLData()) {
$self->{'bug_id'} = $bug_id;
$self->{'error'} = "NotPermitted";
return $self;
} else {
$self->{'bug_id'} = $bug_id;
$self->{'error'} = "NotFound";
return $self;
}
}
$self->{'assigned_to'} = &::DBID_to_name($self->{'assigned_to'});
$self->{'reporter'} = &::DBID_to_name($self->{'reporter'});
my $ccSet = new RelationSet;
$ccSet->mergeFromDB("select who from cc where bug_id=$bug_id");
my @cc = $ccSet->toArrayOfStrings();
if (@cc) {
$self->{'cc'} = \@cc;
}
if (&::Param("useqacontact") && (defined $self->{'qa_contact'}) ) {
my $name = $self->{'qa_contact'} > 0 ? &::DBID_to_name($self->{'qa_contact'}) :"";
if ($name) {
$self->{'qa_contact'} = $name;
}
}
if (@::legal_keywords) {
&::SendSQL("SELECT keyworddefs.name
FROM keyworddefs, keywords
WHERE keywords.bug_id = $bug_id
AND keyworddefs.id = keywords.keywordid
ORDER BY keyworddefs.name");
my @list;
while (&::MoreSQLData()) {
push(@list, &::FetchOneColumn());
}
if (@list) {
$self->{'keywords'} = join(', ', @list);
}
}
&::SendSQL("select attach_id, creation_ts, description
from attachments
where bug_id = $bug_id");
my @attachments;
while (&::MoreSQLData()) {
my ($attachid, $date, $desc) = (&::FetchSQLData());
if ($date =~ /^(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/) {
$date = "$3/$4/$2 $5:$6";
my %attach;
$attach{'attachid'} = $attachid;
$attach{'date'} = $date;
$attach{'desc'} = $desc;
push @attachments, \%attach;
}
}
if (@attachments) {
$self->{'attachments'} = \@attachments;
}
&::SendSQL("select bug_id, who, bug_when, thetext
from longdescs
where bug_id = $bug_id");
my @longdescs;
while (&::MoreSQLData()) {
my ($bug_id, $who, $bug_when, $thetext) = (&::FetchSQLData());
my %longdesc;
$longdesc{'who'} = $who;
$longdesc{'bug_when'} = $bug_when;
$longdesc{'thetext'} = $thetext;
push @longdescs, \%longdesc;
}
if (@longdescs) {
$self->{'longdescs'} = \@longdescs;
}
if (&::Param("usedependencies")) {
my @depends = EmitDependList("blocked", "dependson", $bug_id);
if ( @depends ) {
$self->{'dependson'} = \@depends;
}
my @blocks = EmitDependList("dependson", "blocked", $bug_id);
if ( @blocks ) {
$self->{'blocks'} = \@blocks;
}
}
return $self;
}
# given a bug hash, emit xml for it. with file header provided by caller
#
sub emitXML {
( $#_ == 0 ) || confess("invalid number of arguments");
my $self = shift();
my $xml;
if (exists $self->{'error'}) {
$xml .= "<bug error=\"$self->{'error'}\">\n";
$xml .= " <bug_id>$self->{'bug_id'}</bug_id>\n";
$xml .= "</bug>\n";
return $xml;
}
$xml .= "<bug>\n";
foreach my $field ("bug_id", "bug_status", "product",
"priority", "version", "rep_platform", "assigned_to", "delta_ts",
"component", "reporter", "target_milestone", "bug_severity",
"creation_ts", "qa_contact", "op_sys", "resolution", "bug_file_loc",
"short_desc", "keywords", "status_whiteboard") {
if ($self->{$field}) {
$xml .= " <$field>" . QuoteXMLChars($self->{$field}) . "</$field>\n";
}
}
foreach my $field ("dependson", "blocks", "cc") {
if (defined $self->{$field}) {
for (my $i=0 ; $i < @{$self->{$field}} ; $i++) {
$xml .= " <$field>" . $self->{$field}[$i] . "</$field>\n";
}
}
}
if (defined $self->{'longdescs'}) {
for (my $i=0 ; $i < @{$self->{'longdescs'}} ; $i++) {
$xml .= " <long_desc>\n";
$xml .= " <who>" . &::DBID_to_name($self->{'longdescs'}[$i]->{'who'})
. "</who>\n";
$xml .= " <bug_when>" . $self->{'longdescs'}[$i]->{'bug_when'}
. "</bug_when>\n";
$xml .= " <thetext>" . QuoteXMLChars($self->{'longdescs'}[$i]->{'thetext'})
. "</thetext>\n";
$xml .= " </long_desc>\n";
}
}
if (defined $self->{'attachments'}) {
for (my $i=0 ; $i < @{$self->{'attachments'}} ; $i++) {
$xml .= " <attachment>\n";
$xml .= " <attachid>" . $self->{'attachments'}[$i]->{'attachid'}
. "</attachid>\n";
$xml .= " <date>" . $self->{'attachments'}[$i]->{'date'} . "</date>\n";
$xml .= " <desc>" . QuoteXMLChars($self->{'attachments'}[$i]->{'desc'}) . "</desc>\n";
# $xml .= " <type>" . $self->{'attachments'}[$i]->{'type'} . "</type>\n";
# $xml .= " <data>" . $self->{'attachments'}[$i]->{'data'} . "</data>\n";
$xml .= " </attachment>\n";
}
}
$xml .= "</bug>\n";
return $xml;
}
sub EmitDependList {
my ($myfield, $targetfield, $bug_id) = (@_);
my @list;
&::SendSQL("select dependencies.$targetfield, bugs.bug_status
from dependencies, bugs
where dependencies.$myfield = $bug_id
and bugs.bug_id = dependencies.$targetfield
order by dependencies.$targetfield");
while (&::MoreSQLData()) {
my ($i, $stat) = (&::FetchSQLData());
push @list, $i;
}
return @list;
}
sub QuoteXMLChars {
$_[0] =~ s/&/&amp;/g;
$_[0] =~ s/</&lt;/g;
$_[0] =~ s/>/&gt;/g;
$_[0] =~ s/'/&apos;/g;
$_[0] =~ s/"/&quot;/g;
# $_[0] =~ s/([\x80-\xFF])/&XmlUtf8Encode(ord($1))/ge;
return($_[0]);
}
sub XML_Header {
my ($urlbase, $version, $maintainer, $exporter) = (@_);
my $xml;
$xml = "<?xml version=\"1.0\" standalone=\"yes\"?>\n";
$xml .= "<!DOCTYPE bugzilla SYSTEM \"$urlbase";
if (! ($urlbase =~ /.+\/$/)) {
$xml .= "/";
}
$xml .= "bugzilla.dtd\">\n";
$xml .= "<bugzilla";
if (defined $exporter) {
$xml .= " exporter=\"$exporter\"";
}
$xml .= " version=\"$version\"";
$xml .= " urlbase=\"$urlbase\"";
$xml .= " maintainer=\"$maintainer\">\n";
return ($xml);
}
sub XML_Footer {
return ("</bugzilla>\n");
}
sub UserInGroup {
my $self = shift();
my ($groupname) = (@_);
if ($self->{'usergroupset'} eq "0") {
return 0;
}
&::ConnectToDatabase();
&::SendSQL("select (group_bit & int8($self->{'usergroupset'})) != 0 from groups where name = "
. &::SqlQuote($groupname));
my $bit = &::FetchOneColumn();
if ($bit) {
return 1;
}
return 0;
}
sub CanChangeField {
my $self = shift();
my ($f, $oldvalue, $newvalue) = (@_);
my $UserInEditGroupSet = -1;
my $UserInCanConfirmGroupSet = -1;
my $ownerid;
my $reporterid;
my $qacontactid;
if ($f eq "assigned_to" || $f eq "reporter" || $f eq "qa_contact") {
if ($oldvalue =~ /^\d+$/) {
if ($oldvalue == 0) {
$oldvalue = "";
} else {
$oldvalue = &::DBID_to_name($oldvalue);
}
}
}
if ($oldvalue eq $newvalue) {
return 1;
}
if (&::trim($oldvalue) eq &::trim($newvalue)) {
return 1;
}
if ($f =~ /^longdesc/) {
return 1;
}
if ($UserInEditGroupSet < 0) {
$UserInEditGroupSet = UserInGroup($self, "editbugs");
}
if ($UserInEditGroupSet) {
return 1;
}
&::SendSQL("SELECT reporter, assigned_to, qa_contact FROM bugs " .
"WHERE bug_id = $self->{'bug_id'}");
($reporterid, $ownerid, $qacontactid) = (&::FetchSQLData());
# Let reporter change bug status, even if they can't edit bugs.
# If reporter can't re-open their bug they will just file a duplicate.
# While we're at it, let them close their own bugs as well.
if ( ($f eq "bug_status") && ($self->{'whoid'} eq $reporterid) ) {
return 1;
}
if ($f eq "bug_status" && $newvalue ne $::unconfirmedstate &&
&::IsOpenedState($newvalue)) {
# Hmm. They are trying to set this bug to some opened state
# that isn't the UNCONFIRMED state. Are they in the right
# group? Or, has it ever been confirmed? If not, then this
# isn't legal.
if ($UserInCanConfirmGroupSet < 0) {
$UserInCanConfirmGroupSet = &::UserInGroup("canconfirm");
}
if ($UserInCanConfirmGroupSet) {
return 1;
}
&::SendSQL("SELECT everconfirmed FROM bugs WHERE bug_id = $self->{'bug_id'}");
my $everconfirmed = FetchOneColumn();
if ($everconfirmed) {
return 1;
}
} elsif ($reporterid eq $self->{'whoid'} || $ownerid eq $self->{'whoid'} ||
$qacontactid eq $self->{'whoid'}) {
return 1;
}
$self->{'error'} = "
Only the owner or submitter of the bug, or a sufficiently
empowered user, may make that change to the $f field."
}
sub Collision {
my $self = shift();
my $write = "WRITE"; # Might want to make a param to control
# whether we do LOW_PRIORITY ...
if ($::driver eq 'mysql') {
&::SendSQL("LOCK TABLES bugs $write, bugs_activity $write, cc $write, " .
"cc AS selectVisible_cc $write, " .
"profiles $write, dependencies $write, votes $write, " .
"keywords $write, longdescs $write, fielddefs $write, " .
"keyworddefs READ, groups READ, attachments READ, products READ");
}
&::SendSQL("SELECT delta_ts FROM bugs where bug_id=$self->{'bug_id'}");
my $delta_ts = &::FetchOneColumn();
if ($::driver eq 'mysql') {
&::SendSQL("unlock tables");
}
if ($self->{'delta_ts'} ne $delta_ts) {
return 1;
}
else {
return 0;
}
}
sub AppendComment {
my $self = shift();
my ($comment) = (@_);
$comment =~ s/\r\n/\n/g; # Get rid of windows-style line endings.
$comment =~ s/\r/\n/g; # Get rid of mac-style line endings.
if ($comment =~ /^\s*$/) { # Nothin' but whitespace.
return;
}
&::SendSQL("INSERT INTO longdescs (bug_id, who, bug_when, thetext) " .
"VALUES($self->{'bug_id'}, $self->{'whoid'}, now(), " . &::SqlQuote($comment) . ")");
&::SendSQL("UPDATE bugs SET delta_ts = now() WHERE bug_id = $self->{'bug_id'}");
}
#from o'reilley's Programming Perl
sub display {
my $self = shift;
my @keys;
if (@_ == 0) { # no further arguments
@keys = sort keys(%$self);
} else {
@keys = @_; # use the ones given
}
foreach my $key (@keys) {
print "\t$key => $self->{$key}\n";
}
}
sub CommitChanges {
#snapshot bug
#snapshot dependencies
#check can change fields
#check collision
#lock and change fields
#notify through mail
}
sub AUTOLOAD {
use vars qw($AUTOLOAD);
my $self = shift;
my $type = ref($self) || $self;
my $attr = $AUTOLOAD;
$attr =~ s/.*:://;
return unless $attr=~ /[^A-Z]/;
if (@_) {
$self->{$attr} = shift;
return;
}
confess ("invalid bug attribute $attr") unless $ok_field{$attr};
if (defined $self->{$attr}) {
return $self->{$attr};
} else {
return '';
}
}
1;

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +0,0 @@
* This README is no longer used to house installation instructions. Instead,
it contains pointers to where you may find the information you need.
* Installation instructions are now found in docs/, with a variety of document
types available. Please refer to these documents when installing, configuring,
and maintaining your Bugzilla installation. A helpful starting point is
docs/txt/Bugzilla-Guide.txt, or with a web browser at docs/html/index.html.
* Release notes for people upgrading to a new version of Bugzilla are
available at docs/rel_notes.txt.
* If you wish to contribute to the documentation, please read docs/README.docs.
* The Bugzilla web site is at "http://www.mozilla.org/projects/bugzilla/".
This site will contain the latest Bugzilla information, including how to
report bugs and how to get help with Bugzilla.

View File

@@ -1,268 +0,0 @@
#
# 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 the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 2000 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Dan Mosedale <dmose@mozilla.org>
# Terry Weissman <terry@mozilla.org>
# Dave Miller <justdave@syndicomm.com>
# This object models a set of relations between one item and a group
# of other items. An example is the set of relations between one bug
# and the users CCed on that bug. Currently, the relation objects are
# expected to be bugzilla userids. However, this could and perhaps
# should be generalized to work with non userid objects, such as
# keywords associated with a bug. That shouldn't be hard to do; it
# might involve turning this into a virtual base class, and having
# UserSet and KeywordSet types that inherit from it.
use diagnostics;
use strict;
# Everything that uses RelationSet should already have globals.pl loaded
# so we don't want to load it here. Doing so causes a loop in Perl because
# globals.pl turns around and does a 'use RelationSet'
# See http://bugzilla.mozilla.org/show_bug.cgi?id=72862
#require "globals.pl";
package RelationSet;
use CGI::Carp qw(fatalsToBrowser);
# create a new empty RelationSet
#
sub new {
my $type = shift();
# create a ref to an empty hash and bless it
#
my $self = {};
bless $self, $type;
# construct from a comma-delimited string
#
if ($#_ == 0) {
$self->mergeFromString($_[0]);
}
# unless this was a constructor for an empty list, somebody screwed up.
#
elsif ( $#_ != -1 ) {
confess("invalid number of arguments");
}
# bless as a RelationSet
#
return $self;
}
# Assumes that the set of relations "FROM $table WHERE $constantSql and
# $column = $value" is currently represented by $self, and this set should
# be updated to look like $other.
#
# Returns an array of two strings, one INSERT and one DELETE, which will
# make this change. Either or both strings may be the empty string,
# meaning that no INSERT or DELETE or both (respectively) need to be done.
#
# THE CALLER IS RESPONSIBLE FOR ANY DESIRED LOCKING AND/OR CONSISTENCY
# CHECKS (not to mention doing the SendSQL() calls).
#
sub generateSqlDeltas {
($#_ == 5) || confess("invalid number of arguments");
my ( $self, # instance ptr to set representing the existing state
$endState, # instance ptr to set representing the desired state
$table, # table where these relations are kept
$invariantName, # column held const for a RelationSet (often "bug_id")
$invariantValue, # what to hold the above column constant at
$columnName # the column which varies (often a userid)
) = @_;
# construct the insert list by finding relations which exist in the
# end state but not the current state.
#
my @endStateRelations = keys(%$endState);
my @insertList = ();
foreach ( @endStateRelations ) {
push ( @insertList, $_ ) if ( ! exists $$self{"$_"} );
}
# we've built the list. If it's non-null, add required sql chrome.
#
my $sqlInsert="";
if ( $#insertList > -1 ) {
$sqlInsert = "INSERT INTO $table ($invariantName, $columnName) VALUES " .
join (",",
map ( "($invariantValue, $_)" , @insertList )
);
}
# construct the delete list by seeing which relations exist in the
# current state but not the end state
#
my @selfRelations = keys(%$self);
my @deleteList = ();
foreach ( @selfRelations ) {
push (@deleteList, $_) if ( ! exists $$endState{"$_"} );
}
# we've built the list. if it's non-empty, add required sql chrome.
#
my $sqlDelete = "";
if ( $#deleteList > -1 ) {
$sqlDelete = "DELETE FROM $table WHERE $invariantName = $invariantValue " .
"AND $columnName IN ( " . join (",", @deleteList) . " )";
}
return ($sqlInsert, $sqlDelete);
}
# compare the current object with another.
#
sub isEqual {
($#_ == 1) || confess("invalid number of arguments");
my $self = shift();
my $other = shift();
# get arrays of the keys for faster processing
#
my @selfRelations = keys(%$self);
my @otherRelations = keys(%$other);
# make sure the arrays are the same size
#
return 0 if ( $#selfRelations != $#otherRelations );
# bail out if any of the elements are different
#
foreach my $relation ( @selfRelations ) {
return 0 if ( !exists $$other{$relation})
}
# we made it!
#
return 1;
}
# merge the results of a SQL command into this set
#
sub mergeFromDB {
( $#_ == 1 ) || confess("invalid number of arguments");
my $self = shift();
&::SendSQL(shift());
while (my @row = &::FetchSQLData()) {
$$self{$row[0]} = 1;
}
return;
}
# merge a set in string form into this set
#
sub mergeFromString {
($#_ == 1) || confess("invalid number of arguments");
my $self = shift();
# do the merge
#
foreach my $person (split(/[ ,]/, shift())) {
if ($person ne "") {
$$self{&::DBNameToIdAndCheck($person)} = 1;
}
}
}
# remove a set in string form from this set
#
sub removeItemsInString {
($#_ == 1) || confess("invalid number of arguments");
my $self = shift();
# do the merge
#
foreach my $person (split(/[ ,]/, shift())) {
if ($person ne "") {
my $dbid = &::DBNameToIdAndCheck($person);
if (exists $$self{$dbid}) {
delete $$self{$dbid};
}
}
}
}
# remove a set in array form from this set
#
sub removeItemsInArray {
($#_ > 0) || confess("invalid number of arguments");
my $self = shift();
# do the merge
#
while (my $person = shift()) {
if ($person ne "") {
my $dbid = &::DBNameToIdAndCheck($person);
if (exists $$self{$dbid}) {
delete $$self{$dbid};
}
}
}
}
# return the number of elements in this set
#
sub size {
my $self = shift();
my @k = keys(%$self);
return $#k++;
}
# return this set in array form
#
sub toArray {
my $self= shift();
return keys(%$self);
}
# return this set as an array of strings
#
sub toArrayOfStrings {
($#_ == 0) || confess("invalid number of arguments");
my $self = shift();
my @result = ();
foreach my $i ( keys %$self ) {
push @result, &::DBID_to_name($i);
}
return sort { lc($a) cmp lc($b) } @result;
}
# return this set in string form (comma-separated and sorted)
#
sub toString {
($#_ == 0) || confess("invalid number of arguments");
my $self = shift();
my @result = ();
foreach my $i ( keys %$self ) {
push @result, &::DBID_to_name($i);
}
return join(',', sort(@result));
}
1;

View File

@@ -1,273 +0,0 @@
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# 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 the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Myk Melez <myk@mozilla.org>
################################################################################
# Module Initialization
################################################################################
# Make it harder for us to do dangerous things in Perl.
use diagnostics;
use strict;
# Bundle the functions in this file together into the "Token" package.
package Token;
use Date::Format;
# This module requires that its caller have said "require CGI.pl" to import
# relevant functions from that script and its companion globals.pl.
################################################################################
# Constants
################################################################################
# The maximum number of days a token will remain valid.
my $maxtokenage = 3;
################################################################################
# Functions
################################################################################
sub IssueEmailChangeToken {
my ($userid, $old_email, $new_email) = @_;
my $token_ts = time();
my $issuedate = time2str("%Y-%m-%d %H:%M", $token_ts);
# Generate a unique token and insert it into the tokens table.
# We have to lock the tokens table before generating the token,
# since the database must be queried for token uniqueness.
&::SendSQL("LOCK TABLES tokens WRITE");
my $token = GenerateUniqueToken();
my $quotedtoken = &::SqlQuote($token);
my $quoted_emails = &::SqlQuote($old_email . ":" . $new_email);
&::SendSQL("INSERT INTO tokens ( userid , issuedate , token ,
tokentype , eventdata )
VALUES ( $userid , '$issuedate' , $quotedtoken ,
'emailold' , $quoted_emails )");
my $newtoken = GenerateUniqueToken();
$quotedtoken = &::SqlQuote($newtoken);
&::SendSQL("INSERT INTO tokens ( userid , issuedate , token ,
tokentype , eventdata )
VALUES ( $userid , '$issuedate' , $quotedtoken ,
'emailnew' , $quoted_emails )");
&::SendSQL("UNLOCK TABLES");
# Mail the user the token along with instructions for using it.
my $template = $::template;
my $vars = $::vars;
$vars->{'oldemailaddress'} = $old_email . &::Param('emailsuffix');
$vars->{'newemailaddress'} = $new_email . &::Param('emailsuffix');
$vars->{'max_token_age'} = $maxtokenage;
$vars->{'token_ts'} = $token_ts;
$vars->{'token'} = $token;
$vars->{'emailaddress'} = $old_email . &::Param('emailsuffix');
my $message;
$template->process("account/email/change-old.txt.tmpl", $vars, \$message)
|| &::ThrowTemplateError($template->error());
open SENDMAIL, "|/usr/lib/sendmail -t -i";
print SENDMAIL $message;
close SENDMAIL;
$vars->{'token'} = $newtoken;
$vars->{'emailaddress'} = $new_email . &::Param('emailsuffix');
$message = "";
$template->process("account/email/change-new.txt.tmpl", $vars, \$message)
|| &::ThrowTemplateError($template->error());
open SENDMAIL, "|/usr/lib/sendmail -t -i";
print SENDMAIL $message;
close SENDMAIL;
}
sub IssuePasswordToken {
# Generates a random token, adds it to the tokens table, and sends it
# to the user with instructions for using it to change their password.
my ($loginname) = @_;
# Retrieve the user's ID from the database.
my $quotedloginname = &::SqlQuote($loginname);
&::SendSQL("SELECT userid FROM profiles WHERE login_name = $quotedloginname");
my ($userid) = &::FetchSQLData();
my $token_ts = time();
my $issuedate = time2str("%Y-%m-%d %H:%M", $token_ts);
# Generate a unique token and insert it into the tokens table.
# We have to lock the tokens table before generating the token,
# since the database must be queried for token uniqueness.
&::SendSQL("LOCK TABLE tokens WRITE") if $::driver eq 'mysql';
my $token = GenerateUniqueToken();
my $quotedtoken = &::SqlQuote($token);
my $quotedipaddr = &::SqlQuote($::ENV{'REMOTE_ADDR'});
&::SendSQL("INSERT INTO tokens ( userid , issuedate , token , tokentype , eventdata )
VALUES ( $userid , '$issuedate' , $quotedtoken , 'password' , $quotedipaddr )");
&::SendSQL("UNLOCK TABLES") if $::driver eq 'mysql';
# Mail the user the token along with instructions for using it.
my $template = $::template;
my $vars = $::vars;
$vars->{'token'} = $token;
$vars->{'emailaddress'} = $loginname . &::Param('emailsuffix');
$vars->{'max_token_age'} = $maxtokenage;
$vars->{'token_ts'} = $token_ts;
my $message = "";
$template->process("account/password/forgotten-password.txt.tmpl",
$vars, \$message)
|| &::ThrowTemplateError($template->error());
open SENDMAIL, "|/usr/lib/sendmail -t -i";
print SENDMAIL $message;
close SENDMAIL;
}
sub CleanTokenTable {
&::SendSQL("LOCK TABLES tokens WRITE") if $::driver eq 'mysql';
if ($::driver eq 'mysql') {
&::SendSQL("DELETE FROM tokens WHERE TO_DAYS(NOW()) - TO_DAYS(issuedate) >= " . $maxtokenage);
} elsif ($::driver eq 'Pg') {
&::SendSQL("DELETE FROM tokens WHERE now() - issuedate >= '$maxtokenage days'");
}
&::SendSQL("UNLOCK TABLES") if $::driver eq 'mysql';
}
sub GenerateUniqueToken {
# Generates a unique random token. Uses &GenerateRandomPassword
# for the tokens themselves and checks uniqueness by searching for
# the token in the "tokens" table. Gives up if it can't come up
# with a token after about one hundred tries.
my $token;
my $duplicate = 1;
my $tries = 0;
while ($duplicate) {
++$tries;
if ($tries > 100) {
&::DisplayError("Something is seriously wrong with the token generation system.");
exit;
}
$token = &::GenerateRandomPassword();
&::SendSQL("SELECT userid FROM tokens WHERE token = " . &::SqlQuote($token));
$duplicate = &::FetchSQLData();
}
return $token;
}
sub Cancel {
# Cancels a previously issued token and notifies the system administrator.
# This should only happen when the user accidentally makes a token request
# or when a malicious hacker makes a token request on behalf of a user.
my ($token, $cancelaction) = @_;
# Quote the token for inclusion in SQL statements.
my $quotedtoken = &::SqlQuote($token);
# Get information about the token being cancelled.
&::SendSQL("SELECT issuedate , tokentype , eventdata , login_name , realname
FROM tokens, profiles
WHERE tokens.userid = profiles.userid
AND token = $quotedtoken");
my ($issuedate, $tokentype, $eventdata, $loginname, $realname) = &::FetchSQLData();
# Get the email address of the Bugzilla maintainer.
my $maintainer = &::Param('maintainer');
# Format the user's real name and email address into a single string.
my $username = $realname ? $realname . " <" . $loginname . ">" : $loginname;
my $template = $::template;
my $vars = $::vars;
$vars->{'emailaddress'} = $username;
$vars->{'maintainer'} = $maintainer;
$vars->{'remoteaddress'} = $::ENV{'REMOTE_ADDR'};
$vars->{'token'} = $token;
$vars->{'tokentype'} = $tokentype;
$vars->{'issuedate'} = $issuedate;
$vars->{'eventdata'} = $eventdata;
$vars->{'cancelaction'} = $cancelaction;
# Notify the user via email about the cancellation.
my $message;
$template->process("account/cancel-token.txt.tmpl", $vars, \$message)
|| &::ThrowTemplateError($template->error());
open SENDMAIL, "|/usr/lib/sendmail -t -i";
print SENDMAIL $message;
close SENDMAIL;
# Delete the token from the database.
&::SendSQL("LOCK TABLE tokens WRITE") if $::driver eq 'mysql';
&::SendSQL("DELETE FROM tokens WHERE token = $quotedtoken");
&::SendSQL("UNLOCK TABLES") if $::driver eq 'mysql';
}
sub HasPasswordToken {
# Returns a password token if the user has one.
my ($userid) = @_;
&::SendSQL("SELECT token FROM tokens
WHERE userid = $userid AND tokentype = 'password' LIMIT 1");
my ($token) = &::FetchSQLData();
return $token;
}
sub HasEmailChangeToken {
# Returns an email change token if the user has one.
my ($userid) = @_;
&::SendSQL("SELECT token FROM tokens
WHERE userid = $userid
AND tokentype = 'emailnew'
OR tokentype = 'emailold' LIMIT 1");
my ($token) = &::FetchSQLData();
return $token;
}
1;

View File

@@ -1,3 +0,0 @@
Please consult The Bugzilla Guide for instructions on how to upgrade
Bugzilla from an older version. The Guide can be found with this
distribution, in docs/html, docs/txt, and docs/sgml.

View File

@@ -1,407 +0,0 @@
This file contains only important changes made to Bugzilla before release
2.8. If you are upgrading from version older than 2.8, please read this file.
If you are upgrading from 2.8 or newer, please read the Installation and
Upgrade instructions in The Bugzilla Guide, found with this distribution in
docs/html, docs/txt, and docs/sgml.
For a complete list of what changes, use Bonsai
(http://cvs-mirror.mozilla.org/webtools/bonsai/cvsqueryform.cgi) to
query the CVS tree. For example,
http://cvs-mirror.mozilla.org/webtools/bonsai/cvsquery.cgi?module=all&branch=HEAD&branchtype=match&dir=mozilla%2Fwebtools%2Fbugzilla&file=&filetype=match&who=&whotype=match&sortby=Date&hours=2&date=week&mindate=&maxdate=&cvsroot=%2Fcvsroot
will tell you what has been changed in the last week.
10/12/99 The CHANGES file is now obsolete! There is a new file called
checksetup.pl. You should get in the habit of running that file every time
you update your installation of Bugzilla. That file will be constantly
updated to automatically update your installation to match any code changes.
If you're curious as to what is going on, changes are commented in that file,
at the end.
Many thanks to Holger Schurig <holgerschurig@nikocity.de> for writing this
script!
10/11/99 Restructured voting database to add a cached value in each
bug recording how many total votes that bug has. While I'm at it, I
removed the unused "area" field from the bugs database. It is
distressing to realize that the bugs table has reached the maximum
number of indices allowed by MySQL (16), which may make future
enhancements awkward.
You must feed the following to MySQL:
alter table bugs drop column area;
alter table bugs add column votes mediumint not null, add index (votes);
You then *must* delete the data/versioncache file when you make this
change, as it contains references to the "area" field. Deleting it is safe,
bugzilla will correctly regenerate it.
If you have been using the voting feature at all, then you will then
need to update the voting cache. You can do this by visiting the
sanitycheck.cgi page, and taking it up on its offer to rebuild the
votes stuff.
10/7/99 Added voting ability. You must run the new script
"makevotestable.sh". You must also feed the following to mysql:
alter table products add column votesperuser smallint not null;
9/15/99 Apparently, newer alphas of MySQL won't allow you to have
"when" as a column name. So, I have had to rename a column in the
bugs_activity table. You must feed the below to mysql or you won't
work at all.
alter table bugs_activity change column when bug_when datetime not null;
8/16/99 Added "OpenVMS" to the list of OS's. Feed this to mysql:
alter table bugs change column op_sys op_sys enum("All", "Windows 3.1", "Windows 95", "Windows 98", "Windows NT", "Mac System 7", "Mac System 7.5", "Mac System 7.6.1", "Mac System 8.0", "Mac System 8.5", "Mac System 8.6", "AIX", "BSDI", "HP-UX", "IRIX", "Linux", "FreeBSD", "OSF/1", "Solaris", "SunOS", "Neutrino", "OS/2", "BeOS", "OpenVMS", "other") not null;
6/22/99 Added an entry to the attachments table to record who the submitter
was. Nothing uses this yet, but it still should be recorded.
alter table attachments add column submitter_id mediumint not null;
You should also run this script to populate the new field:
#!/usr/bonsaitools/bin/perl -w
use diagnostics;
use strict;
require "globals.pl";
$|=1;
ConnectToDatabase();
SendSQL("select bug_id, attach_id from attachments order by bug_id");
my @list;
while (MoreSQLData()) {
my @row = FetchSQLData();
push(@list, \@row);
}
foreach my $ref (@list) {
my ($bug, $attach) = (@$ref);
SendSQL("select long_desc from bugs where bug_id = $bug");
my $comment = FetchOneColumn() . "Created an attachment (id=$attach)";
if ($comment =~ m@-* Additional Comments From ([^ ]*)[- 0-9/:]*\nCreated an attachment \(id=$attach\)@) {
print "Found $1\n";
SendSQL("select userid from profiles where login_name=" .
SqlQuote($1));
my $userid = FetchOneColumn();
if (defined $userid && $userid > 0) {
SendSQL("update attachments set submitter_id=$userid where attach_id = $attach");
}
} else {
print "Bug $bug can't find comment for attachment $attach\n";
}
}
6/14/99 Added "BeOS" to the list of OS's. Feed this to mysql:
alter table bugs change column op_sys op_sys enum("All", "Windows 3.1", "Windows 95", "Windows 98", "Windows NT", "Mac System 7", "Mac System 7.5", "Mac System 7.6.1", "Mac System 8.0", "Mac System 8.5", "Mac System 8.6", "AIX", "BSDI", "HP-UX", "IRIX", "Linux", "FreeBSD", "OSF/1", "Solaris", "SunOS", "Neutrino", "OS/2", "BeOS", "other") not null;
5/27/99 Added support for dependency information. You must run the new
"makedependenciestable.sh" script. You can turn off dependencies with the new
"usedependencies" param, but it defaults to being on. Also, read very
carefully the description for the new "webdotbase" param; you will almost
certainly need to tweak it.
5/24/99 Added "Mac System 8.6" and "Neutrino" to the list of OS's.
Feed this to mysql:
alter table bugs change column op_sys op_sys enum("All", "Windows 3.1", "Windows 95", "Windows 98", "Windows NT", "Mac System 7", "Mac System 7.5", "Mac System 7.6.1", "Mac System 8.0", "Mac System 8.5", "Mac System 8.6", "AIX", "BSDI", "HP-UX", "IRIX", "Linux", "FreeBSD", "OSF/1", "Solaris", "SunOS", "Neutrino", "OS/2", "other") not null;
5/12/99 Added a pref to control how much email you get. This needs a new
column in the profiles table, so feed the following to mysql:
alter table profiles add column emailnotification enum("ExcludeSelfChanges", "CConly", "All") not null default "ExcludeSelfChanges";
5/5/99 Added the ability to search by creation date. To make this perform
well, you ought to do the following:
alter table bugs change column creation_ts creation_ts datetime not null, add index (creation_ts);
4/30/99 Added a new severity, "blocker". To get this into your running
Bugzilla, do the following:
alter table bugs change column bug_severity bug_severity enum("blocker", "critical", "major", "normal", "minor", "trivial", "enhancement") not null;
4/22/99 There was a bug where the long descriptions of bugs had a variety of
newline characters at the end, depending on the operating system of the browser
that submitted the text. This bug has been fixed, so that no further changes
like that will happen. But to fix problems that have already crept into your
database, you can run the following perl script (which is slow and ugly, but
does work:)
#!/usr/bonsaitools/bin/perl -w
use diagnostics;
use strict;
require "globals.pl";
$|=1;
ConnectToDatabase();
SendSQL("select bug_id from bugs order by bug_id");
my @list;
while (MoreSQLData()) {
push(@list, FetchOneColumn());
}
foreach my $id (@list) {
if ($id % 50 == 0) {
print "\n$id ";
}
SendSQL("select long_desc from bugs where bug_id = $id");
my $comment = FetchOneColumn();
my $orig = $comment;
$comment =~ s/\r\n/\n/g; # Get rid of windows-style line endings.
$comment =~ s/\r/\n/g; # Get rid of mac-style line endings.
if ($comment ne $orig) {
SendSQL("update bugs set long_desc = " . SqlQuote($comment) .
" where bug_id = $id");
print ".";
} else {
print "-";
}
}
4/8/99 Added ability to store patches with bugs. This requires a new table
to store the data, so you will need to run the "makeattachmenttable.sh" script.
3/25/99 Unfortunately, the HTML::FromText CPAN module had too many bugs, and
so I had to roll my own. We no longer use the HTML::FromText CPAN module.
3/24/99 (This entry has been removed. It used to say that we required the
HTML::FromText CPAN module, but that's no longer true.)
3/22/99 Added the ability to query by fields which have changed within a date
range. To make this perform a bit better, we need a new index:
alter table bugs_activity add index (field);
3/10/99 Added 'groups' stuff, where we have different group bits that we can
put on a person or on a bug. Some of the group bits control access to bugzilla
features. And a person can't access a bug unless he has every group bit set
that is also set on the bug. See the comments in makegroupstable.sh for a bit
more info.
The 'maintainer' param is now used only as an email address for people to send
complaints to. The groups table is what is now used to determine permissions.
You will need to run the new script "makegroupstable.sh". And then you need to
feed the following lines to MySQL (replace XXX with the login name of the
maintainer, the person you wish to be all-powerful).
alter table bugs add column groupset bigint not null;
alter table profiles add column groupset bigint not null;
update profiles set groupset=0x7fffffffffffffff where login_name = XXX;
3/8/99 Added params to control how priorities are set in a new bug. You can
now choose whether to let submitters of new bugs choose a priority, or whether
they should just accept the default priority (which is now no longer hardcoded
to "P2", but is instead a param.) The default value of the params will cause
the same behavior as before.
3/3/99 Added a "disallownew" field to the products table. If non-zero, then
don't let people file new bugs against this product. (This is for when a
product is retired, but you want to keep the bug reports around for posterity.)
Feed this to MySQL:
alter table products add column disallownew tinyint not null;
2/8/99 Added FreeBSD to the list of OS's. Feed this to MySQL:
alter table bugs change column op_sys op_sys enum("All", "Windows 3.1", "Windows 95", "Windows 98", "Windows NT", "Mac System 7", "Mac System 7.5", "Mac System 7.6.1", "Mac System 8.0", "Mac System 8.5", "AIX", "BSDI", "HP-UX", "IRIX", "Linux", "FreeBSD", "OSF/1", "Solaris", "SunOS", "OS/2", "other") not null;
2/4/99 Added a new column "description" to the components table, and added
links to a new page which will use this to describe the components of a
given product. Feed this to MySQL:
alter table components add column description mediumtext not null;
2/3/99 Added a new column "initialqacontact" to the components table that gives
an initial QA contact field. It may be empty if you wish the initial qa
contact to be empty. If you're not using the QA contact field, you don't need
to add this column, but you might as well be safe and add it anyway:
alter table components add column initialqacontact tinytext not null;
2/2/99 Added a new column "milestoneurl" to the products table that gives a URL
which is to describe the currently defined milestones for a product. If you
don't use target milestone, you might be able to get away without adding this
column, but you might as well be safe and add it anyway:
alter table products add column milestoneurl tinytext not null;
1/29/99 Whoops; had a misspelled op_sys. It was "Mac System 7.1.6"; it should
be "Mac System 7.6.1". It turns out I had no bugs with this value set, so I
could just do the below simple command. If you have bugs with this value, you
may need to do something more complicated.
alter table bugs change column op_sys op_sys enum("All", "Windows 3.1", "Windows 95", "Windows 98", "Windows NT", "Mac System 7", "Mac System 7.5", "Mac System 7.6.1", "Mac System 8.0", "Mac System 8.5", "AIX", "BSDI", "HP-UX", "IRIX", "Linux", "OSF/1", "Solaris", "SunOS", "OS/2", "other") not null;
1/20/99 Added new fields: Target Milestone, QA Contact, and Status Whiteboard.
These fields are all optional in the UI; there are parameters to turn them on.
However, whether or not you use them, the fields need to be in the DB. There
is some code that needs them, even if you don't.
To update your DB to have these fields, send the following to MySQL:
alter table bugs add column target_milestone varchar(20) not null,
add column qa_contact mediumint not null,
add column status_whiteboard mediumtext not null,
add index (target_milestone), add index (qa_contact);
1/18/99 You can now query by CC. To make this perform reasonably, the CC table
needs some indices. The following MySQL does the necessary stuff:
alter table cc add index (bug_id), add index (who);
1/15/99 The op_sys field can now be queried by (and more easily tweaked).
To make this perform reasonably, it needs an index. The following MySQL
command will create the necessary index:
alter table bugs add index (op_sys);
12/2/98 The op_sys and rep_platform fields have been tweaked. op_sys
is now an enum, rather than having the legal values all hard-coded in
perl. rep_platform now no longer allows a value of "X-Windows".
Here's how I ported to the new world. This ought to work for you too.
Actually, it's probably overkill. I had a lot of illegal values for op_sys
in my tables, from importing bugs from strange places. If you haven't done
anything funky, then much of the below will be a no-op.
First, send the following commands to MySQL to make sure all your values for
rep_platform and op_sys are legal in the new world..
update bugs set rep_platform="Sun" where rep_platform="X-Windows" and op_sys like "Solaris%";
update bugs set rep_platform="SGI" where rep_platform="X-Windows" and op_sys = "IRIX";
update bugs set rep_platform="SGI" where rep_platform="X-Windows" and op_sys = "HP-UX";
update bugs set rep_platform="DEC" where rep_platform="X-Windows" and op_sys = "OSF/1";
update bugs set rep_platform="PC" where rep_platform="X-Windows" and op_sys = "Linux";
update bugs set rep_platform="other" where rep_platform="X-Windows";
update bugs set rep_platform="other" where rep_platform="";
update bugs set op_sys="Mac System 7" where op_sys="System 7";
update bugs set op_sys="Mac System 7.5" where op_sys="System 7.5";
update bugs set op_sys="Mac System 8.0" where op_sys="8.0";
update bugs set op_sys="OSF/1" where op_sys="Digital Unix 4.0";
update bugs set op_sys="IRIX" where op_sys like "IRIX %";
update bugs set op_sys="HP-UX" where op_sys like "HP-UX %";
update bugs set op_sys="Windows NT" where op_sys like "NT %";
update bugs set op_sys="OSF/1" where op_sys like "OSF/1 %";
update bugs set op_sys="Solaris" where op_sys like "Solaris %";
update bugs set op_sys="SunOS" where op_sys like "SunOS%";
update bugs set op_sys="other" where op_sys = "Motif";
update bugs set op_sys="other" where op_sys = "Other";
Next, send the following commands to make sure you now have only legal
entries in your table. If either of the queries do not come up empty, then
you have to do more stuff like the above.
select bug_id,op_sys,rep_platform from bugs where rep_platform not regexp "^(All|DEC|HP|Macintosh|PC|SGI|Sun|X-Windows|Other)$";
select bug_id,op_sys,rep_platform from bugs where op_sys not regexp "^(All|Windows 3.1|Windows 95|Windows 98|Windows NT|Mac System 7|Mac System 7.5|Mac System 7.1.6|Mac System 8.0|AIX|BSDI|HP-UX|IRIX|Linux|OSF/1|Solaris|SunOS|other)$";
Finally, once that's all clear, alter the table to make enforce the new legal
entries:
alter table bugs change column op_sys op_sys enum("All", "Windows 3.1", "Windows 95", "Windows 98", "Windows NT", "Mac System 7", "Mac System 7.5", "Mac System 7.1.6", "Mac System 8.0", "AIX", "BSDI", "HP-UX", "IRIX", "Linux", "OSF/1", "Solaris", "SunOS", "other") not null, change column rep_platform rep_platform enum("All", "DEC", "HP", "Macintosh", "PC", "SGI", "Sun", "Other");
11/20/98 Added searching of CC field. To better support this, added
some indexes to the CC table. You probably want to execute the following
mysql commands:
alter table cc add index (bug_id);
alter table cc add index (who);
10/27/98 security check for legal products in place. bug charts are not
available as an option if collectstats.pl has never been run. all products
get daily stats collected now. README updated: Chart::Base is listed as
a requirement, instructions for using collectstats.pl included as
an optional step. also got silly and added optional quips to bug
reports.
10/17/98 modified README installation instructions slightly.
10/7/98 Added a new table called "products". Right now, this is used
only to have a description for each product, and that description is
only used when initially adding a new bug. Anyway, you *must* create
the new table (which you can do by running the new makeproducttable.sh
script). If you just leave it empty, things will work much as they
did before, or you can add descriptions for some or all of your
products.
9/15/98 Everything has been ported to Perl. NO MORE TCL. This
transition should be relatively painless, except for the "params"
file. This is the file that contains parameters you've set up on the
editparams.cgi page. Before changing to Perl, this was a tcl-syntax
file, stored in the same directory as the code; after the change to
Perl, it becomes a perl-syntax file, stored in a subdirectory named
"data". See the README file for more details on what version of Perl
you need.
So, if updating from an older version of Bugzilla, you will need to
edit data/param, change the email address listed for
$::param{'maintainer'}, and then go revisit the editparams.cgi page
and reset all the parameters to your taste. Fortunately, your old
params file will still be around, and so you ought to be able to
cut&paste important bits from there.
Also, note that the "whineatnews" script has changed name (it now has
an extension of .pl instead of .tcl), so you'll need to change your
cron job.
And the "comments" file has been moved to the data directory. Just do
"cat comments >> data/comments" to restore any old comments that may
have been lost.
9/2/98 Changed the way password validation works. We now keep a
crypt'd version of the password in the database, and check against
that. (This is silly, because we're also keeping the plaintext
version there, but I have plans...) Stop passing the plaintext
password around as a cookie; instead, we have a cookie that references
a record in a new database table, logincookies.
IMPORTANT: if updating from an older version of Bugzilla, you must run
the following commands to keep things working:
./makelogincookiestable.sh
echo "alter table profiles add column cryptpassword varchar(64);" | mysql bugs
echo "update profiles set cryptpassword = encrypt(password,substring(rand(),3, 4));" | mysql bugs

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

View File

@@ -1,792 +0,0 @@
#!/usr/bonsaitools/bin/perl -wT
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# 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 the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Terry Weissman <terry@mozilla.org>
# Myk Melez <myk@mozilla.org>
################################################################################
# Script Initialization
################################################################################
# Make it harder for us to do dangerous things in Perl.
use diagnostics;
use strict;
use lib qw(.);
use vars qw(
$template
$vars
);
# Include the Bugzilla CGI and general utility library.
require "CGI.pl";
# Establish a connection to the database backend.
ConnectToDatabase();
# Check whether or not the user is logged in and, if so, set the $::userid
# and $::usergroupset variables.
quietly_check_login();
################################################################################
# Main Body Execution
################################################################################
# All calls to this script should contain an "action" variable whose value
# determines what the user wants to do. The code below checks the value of
# that variable and runs the appropriate code.
# Determine whether to use the action specified by the user or the default.
my $action = $::FORM{'action'} || 'view';
if ($action eq "view")
{
validateID();
view();
}
elsif ($action eq "viewall")
{
ValidateBugID($::FORM{'bugid'});
viewall();
}
elsif ($action eq "enter")
{
confirm_login();
ValidateBugID($::FORM{'bugid'});
enter();
}
elsif ($action eq "insert")
{
confirm_login();
ValidateBugID($::FORM{'bugid'});
ValidateComment($::FORM{'comment'});
validateFilename();
validateData();
validateDescription();
validateIsPatch();
validateContentType() unless $::FORM{'ispatch'};
validateObsolete() if $::FORM{'obsolete'};
insert();
}
elsif ($action eq "edit")
{
quietly_check_login();
validateID();
validateCanEdit($::FORM{'id'});
edit();
}
elsif ($action eq "update")
{
confirm_login();
ValidateComment($::FORM{'comment'});
validateID();
validateCanEdit($::FORM{'id'});
validateDescription();
validateIsPatch();
validateContentType() unless $::FORM{'ispatch'};
validateIsObsolete();
validateStatuses();
update();
}
else
{
DisplayError("I could not figure out what you wanted to do.")
}
exit;
################################################################################
# Data Validation / Security Authorization
################################################################################
sub validateID
{
# Validate the value of the "id" form field, which must contain an
# integer that is the ID of an existing attachment.
detaint_natural($::FORM{'id'})
|| DisplayError("You did not enter a valid attachment number.")
&& exit;
# Make sure the attachment exists in the database.
SendSQL("SELECT bug_id FROM attachments WHERE attach_id = $::FORM{'id'}");
MoreSQLData()
|| DisplayError("Attachment #$::FORM{'id'} does not exist.")
&& exit;
# Make sure the user is authorized to access this attachment's bug.
my ($bugid) = FetchSQLData();
ValidateBugID($bugid);
}
sub validateCanEdit
{
my ($attach_id) = (@_);
# If the user is not logged in, claim that they can edit. This allows
# the edit scrren to be displayed to people who aren't logged in.
# People not logged in can't actually commit changes, because that code
# calls confirm_login, not quietly_check_login, before calling this sub
return if $::userid == 0;
# People in editbugs can edit all attachments
return if UserInGroup("editbugs");
# Bug 97729 - the submitter can edit their attachments
SendSQL("SELECT attach_id FROM attachments WHERE " .
"attach_id = $attach_id AND submitter_id = $::userid");
FetchSQLData()
|| DisplayError("You are not authorised to edit attachment #$attach_id")
&& exit;
}
sub validateDescription
{
$::FORM{'description'}
|| DisplayError("You must enter a description for the attachment.")
&& exit;
}
sub validateIsPatch
{
# Set the ispatch flag to zero if it is undefined, since the UI uses
# an HTML checkbox to represent this flag, and unchecked HTML checkboxes
# do not get sent in HTML requests.
$::FORM{'ispatch'} = $::FORM{'ispatch'} ? 1 : 0;
# Set the content type to text/plain if the attachment is a patch.
$::FORM{'contenttype'} = "text/plain" if $::FORM{'ispatch'};
}
sub validateContentType
{
if (!$::FORM{'contenttypemethod'})
{
DisplayError("You must choose a method for determining the content type,
either <em>auto-detect</em>, <em>select from list</em>, or <em>enter
manually</em>.");
exit;
}
elsif ($::FORM{'contenttypemethod'} eq 'autodetect')
{
# The user asked us to auto-detect the content type, so use the type
# specified in the HTTP request headers.
if ( !$::FILE{'data'}->{'contenttype'} )
{
DisplayError("You asked Bugzilla to auto-detect the content type, but
your browser did not specify a content type when uploading the file,
so you must enter a content type manually.");
exit;
}
$::FORM{'contenttype'} = $::FILE{'data'}->{'contenttype'};
}
elsif ($::FORM{'contenttypemethod'} eq 'list')
{
# The user selected a content type from the list, so use their selection.
$::FORM{'contenttype'} = $::FORM{'contenttypeselection'};
}
elsif ($::FORM{'contenttypemethod'} eq 'manual')
{
# The user entered a content type manually, so use their entry.
$::FORM{'contenttype'} = $::FORM{'contenttypeentry'};
}
else
{
my $htmlcontenttypemethod = html_quote($::FORM{'contenttypemethod'});
DisplayError("Your form submission got corrupted somehow. The <em>content
method</em> field, which specifies how the content type gets determined,
should have been either <em>autodetect</em>, <em>list</em>,
or <em>manual</em>, but was instead <em>$htmlcontenttypemethod</em>.");
exit;
}
if ( $::FORM{'contenttype'} !~ /^(application|audio|image|message|model|multipart|text|video)\/.+$/ )
{
my $htmlcontenttype = html_quote($::FORM{'contenttype'});
DisplayError("The content type <em>$htmlcontenttype</em> is invalid.
Valid types must be of the form <em>foo/bar</em> where <em>foo</em>
is either <em>application, audio, image, message, model, multipart,
text,</em> or <em>video</em>.");
exit;
}
}
sub validateIsObsolete
{
# Set the isobsolete flag to zero if it is undefined, since the UI uses
# an HTML checkbox to represent this flag, and unchecked HTML checkboxes
# do not get sent in HTML requests.
$::FORM{'isobsolete'} = $::FORM{'isobsolete'} ? 1 : 0;
}
sub validateStatuses
{
# Get a list of attachment statuses that are valid for this attachment.
PushGlobalSQLState();
SendSQL("SELECT attachstatusdefs.id
FROM attachments, bugs, attachstatusdefs
WHERE attachments.attach_id = $::FORM{'id'}
AND attachments.bug_id = bugs.bug_id
AND attachstatusdefs.product = bugs.product");
my @statusdefs;
push(@statusdefs, FetchSQLData()) while MoreSQLData();
PopGlobalSQLState();
foreach my $status (@{$::MFORM{'status'}})
{
grep($_ == $status, @statusdefs)
|| DisplayError("One of the statuses you entered is not a valid status
for this attachment.")
&& exit;
# We have tested that the status is valid, so it can be detainted
detaint_natural($status);
}
}
sub validateData
{
$::FORM{'data'}
|| DisplayError("The file you are trying to attach is empty!")
&& exit;
my $len = length($::FORM{'data'});
my $maxpatchsize = Param('maxpatchsize');
my $maxattachmentsize = Param('maxattachmentsize');
# Makes sure the attachment does not exceed either the "maxpatchsize" or
# the "maxattachmentsize" parameter.
if ( $::FORM{'ispatch'} && $maxpatchsize && $len > $maxpatchsize*1024 )
{
my $lenkb = sprintf("%.0f", $len/1024);
DisplayError("The file you are trying to attach is ${lenkb} kilobytes (KB) in size.
Patches cannot be more than ${maxpatchsize}KB in size.
Try breaking your patch into several pieces.");
exit;
} elsif ( !$::FORM{'ispatch'} && $maxattachmentsize && $len > $maxattachmentsize*1024 ) {
my $lenkb = sprintf("%.0f", $len/1024);
DisplayError("The file you are trying to attach is ${lenkb} kilobytes (KB) in size.
Non-patch attachments cannot be more than ${maxattachmentsize}KB.
If your attachment is an image, try converting it to a compressable
format like JPG or PNG, or put it elsewhere on the web and
link to it from the bug's URL field or in a comment on the bug.");
exit;
}
}
sub validateFilename
{
defined $::FILE{'data'}
|| DisplayError("You did not specify a file to attach.")
&& exit;
}
sub validateObsolete
{
# Make sure the attachment id is valid and the user has permissions to view
# the bug to which it is attached.
foreach my $attachid (@{$::MFORM{'obsolete'}}) {
detaint_natural($attachid)
|| DisplayError("The attachment number of one of the attachments
you wanted to obsolete is invalid.")
&& exit;
SendSQL("SELECT bug_id, isobsolete, description
FROM attachments WHERE attach_id = $attachid");
# Make sure the attachment exists in the database.
MoreSQLData()
|| DisplayError("Attachment #$attachid does not exist.")
&& exit;
my ($bugid, $isobsolete, $description) = FetchSQLData();
if ($bugid != $::FORM{'bugid'})
{
$description = html_quote($description);
DisplayError("Attachment #$attachid ($description) is attached
to bug #$bugid, but you tried to flag it as obsolete while
creating a new attachment to bug #$::FORM{'bugid'}.");
exit;
}
if ( $isobsolete )
{
$description = html_quote($description);
DisplayError("Attachment #$attachid ($description) is already obsolete.");
exit;
}
# Check that the user can modify this attachment
validateCanEdit($attachid);
}
}
################################################################################
# Functions
################################################################################
sub view
{
# Display an attachment.
# Retrieve the attachment content and its content type from the database.
SendSQL("SELECT mimetype, thedata FROM attachments WHERE attach_id = $::FORM{'id'}");
my ($contenttype, $thedata) = FetchSQLData();
# Return the appropriate HTTP response headers.
print "Content-Type: $contenttype\n\n";
print $thedata;
}
sub viewall
{
# Display all attachments for a given bug in a series of IFRAMEs within one HTML page.
# Retrieve the attachments from the database and write them into an array
# of hashes where each hash represents one attachment.
SendSQL("SELECT attach_id, creation_ts, mimetype, description, ispatch, isobsolete
FROM attachments WHERE bug_id = $::FORM{'bugid'} ORDER BY attach_id");
my @attachments; # the attachments array
while (MoreSQLData())
{
my %a; # the attachment hash
($a{'attachid'}, $a{'date'}, $a{'contenttype'},
$a{'description'}, $a{'ispatch'}, $a{'isobsolete'}) = FetchSQLData();
# Format the attachment's creation/modification date into something readable.
if ($a{'date'} =~ /^(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/) {
$a{'date'} = "$3/$4/$2&nbsp;$5:$6";
}
# Flag attachments as to whether or not they can be viewed (as opposed to
# being downloaded). Currently I decide they are viewable if their MIME type
# is either text/*, image/*, or application/vnd.mozilla.*.
# !!! Yuck, what an ugly hack. Fix it!
$a{'isviewable'} = ( $a{'contenttype'} =~ /^(text|image|application\/vnd\.mozilla\.)/ );
# Retrieve a list of status flags that have been set on the attachment.
PushGlobalSQLState();
SendSQL("SELECT name
FROM attachstatuses, attachstatusdefs
WHERE attach_id = $a{'attachid'}
AND attachstatuses.statusid = attachstatusdefs.id
ORDER BY sortkey");
my @statuses;
push(@statuses, FetchSQLData()) while MoreSQLData();
$a{'statuses'} = \@statuses;
PopGlobalSQLState();
# Add the hash representing the attachment to the array of attachments.
push @attachments, \%a;
}
# Retrieve the bug summary for displaying on screen.
SendSQL("SELECT short_desc FROM bugs WHERE bug_id = $::FORM{'bugid'}");
my ($bugsummary) = FetchSQLData();
# Define the variables and functions that will be passed to the UI template.
$vars->{'bugid'} = $::FORM{'bugid'};
$vars->{'bugsummary'} = $bugsummary;
$vars->{'attachments'} = \@attachments;
# Return the appropriate HTTP response headers.
print "Content-Type: text/html\n\n";
# Generate and return the UI (HTML page) from the appropriate template.
$template->process("attachment/show-multiple.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
}
sub enter
{
# Display a form for entering a new attachment.
# Retrieve the attachments the user can edit from the database and write
# them into an array of hashes where each hash represents one attachment.
my $canEdit = "";
if (!UserInGroup("editbugs")) {
$canEdit = "AND submitter_id = $::userid";
}
SendSQL("SELECT attach_id, description
FROM attachments
WHERE bug_id = $::FORM{'bugid'}
AND isobsolete = 0 $canEdit
ORDER BY attach_id");
my @attachments; # the attachments array
while ( MoreSQLData() ) {
my %a; # the attachment hash
($a{'id'}, $a{'description'}) = FetchSQLData();
# Add the hash representing the attachment to the array of attachments.
push @attachments, \%a;
}
# Retrieve the bug summary for displaying on screen.
SendSQL("SELECT short_desc FROM bugs WHERE bug_id = $::FORM{'bugid'}");
my ($bugsummary) = FetchSQLData();
# Define the variables and functions that will be passed to the UI template.
$vars->{'bugid'} = $::FORM{'bugid'};
$vars->{'bugsummary'} = $bugsummary;
$vars->{'attachments'} = \@attachments;
# Return the appropriate HTTP response headers.
print "Content-Type: text/html\n\n";
# Generate and return the UI (HTML page) from the appropriate template.
$template->process("attachment/create.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
}
sub insert
{
# Insert a new attachment into the database.
# Escape characters in strings that will be used in SQL statements.
my $filename = SqlQuote($::FILE{'data'}->{'filename'});
my $description = SqlQuote($::FORM{'description'});
my $contenttype = SqlQuote($::FORM{'contenttype'});
my $thedata = SqlQuote($::FORM{'data'});
# Insert the attachment into the database.
SendSQL("INSERT INTO attachments (bug_id, filename, description, mimetype, ispatch, submitter_id, thedata)
VALUES ($::FORM{'bugid'}, $filename, $description, $contenttype, $::FORM{'ispatch'}, $::userid, $thedata)");
# Retrieve the ID of the newly created attachment record.
SendSQL("SELECT LAST_INSERT_ID()");
my $attachid = FetchOneColumn();
# Insert a comment about the new attachment into the database.
my $comment = "Created an attachment (id=$attachid)\n$::FORM{'description'}\n";
$comment .= ("\n" . $::FORM{'comment'}) if $::FORM{'comment'};
use Text::Wrap;
$Text::Wrap::columns = 80;
$Text::Wrap::huge = 'overflow';
$comment = Text::Wrap::wrap('', '', $comment);
AppendComment($::FORM{'bugid'},
$::COOKIE{"Bugzilla_login"},
$comment);
# Make existing attachments obsolete.
my $fieldid = GetFieldID('attachments.isobsolete');
foreach my $attachid (@{$::MFORM{'obsolete'}}) {
SendSQL("UPDATE attachments SET isobsolete = 1 WHERE attach_id = $attachid");
SendSQL("INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
VALUES ($::FORM{'bugid'}, $attachid, $::userid, NOW(), $fieldid, '0', '1')");
}
# Send mail to let people know the attachment has been created. Uses a
# special syntax of the "open" and "exec" commands to capture the output of
# "processmail", which "system" doesn't allow, without running the command
# through a shell, which backticks (``) do.
#system ("./processmail", $bugid , $::userid);
#my $mailresults = `./processmail $bugid $::userid`;
my $mailresults = '';
open(PMAIL, "-|") or exec('./processmail', $::FORM{'bugid'}, $::COOKIE{'Bugzilla_login'});
$mailresults .= $_ while <PMAIL>;
close(PMAIL);
# Define the variables and functions that will be passed to the UI template.
$vars->{'bugid'} = $::FORM{'bugid'};
$vars->{'attachid'} = $attachid;
$vars->{'description'} = $description;
$vars->{'mailresults'} = $mailresults;
$vars->{'contenttypemethod'} = $::FORM{'contenttypemethod'};
$vars->{'contenttype'} = $::FORM{'contenttype'};
# Return the appropriate HTTP response headers.
print "Content-Type: text/html\n\n";
# Generate and return the UI (HTML page) from the appropriate template.
$template->process("attachment/created.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
}
sub edit
{
# Edit an attachment record. Users with "editbugs" privileges, (or the
# original attachment's submitter) can edit the attachment's description,
# content type, ispatch and isobsolete flags, and statuses, and they can
# also submit a comment that appears in the bug.
# Users cannot edit the content of the attachment itself.
# Retrieve the attachment from the database.
SendSQL("SELECT description, mimetype, bug_id, ispatch, isobsolete
FROM attachments WHERE attach_id = $::FORM{'id'}");
my ($description, $contenttype, $bugid, $ispatch, $isobsolete) = FetchSQLData();
# Flag attachment as to whether or not it can be viewed (as opposed to
# being downloaded). Currently I decide it is viewable if its content
# type is either text/.* or application/vnd.mozilla.*.
# !!! Yuck, what an ugly hack. Fix it!
my $isviewable = ( $contenttype =~ /^(text|image|application\/vnd\.mozilla\.)/ );
# Retrieve a list of status flags that have been set on the attachment.
my %statuses;
SendSQL("SELECT id, name
FROM attachstatuses JOIN attachstatusdefs
WHERE attachstatuses.statusid = attachstatusdefs.id
AND attach_id = $::FORM{'id'}");
while ( my ($id, $name) = FetchSQLData() )
{
$statuses{$id} = $name;
}
# Retrieve a list of statuses for this bug's product, and build an array
# of hashes in which each hash is a status flag record.
# ???: Move this into versioncache or its own routine?
my @statusdefs;
SendSQL("SELECT id, name
FROM attachstatusdefs, bugs
WHERE bug_id = $bugid
AND attachstatusdefs.product = bugs.product
ORDER BY sortkey");
while ( MoreSQLData() )
{
my ($id, $name) = FetchSQLData();
push @statusdefs, { 'id' => $id , 'name' => $name };
}
# Retrieve a list of attachments for this bug as well as a summary of the bug
# to use in a navigation bar across the top of the screen.
SendSQL("SELECT attach_id FROM attachments WHERE bug_id = $bugid ORDER BY attach_id");
my @bugattachments;
push(@bugattachments, FetchSQLData()) while (MoreSQLData());
SendSQL("SELECT short_desc FROM bugs WHERE bug_id = $bugid");
my ($bugsummary) = FetchSQLData();
# Define the variables and functions that will be passed to the UI template.
$vars->{'attachid'} = $::FORM{'id'};
$vars->{'description'} = $description;
$vars->{'contenttype'} = $contenttype;
$vars->{'bugid'} = $bugid;
$vars->{'bugsummary'} = $bugsummary;
$vars->{'ispatch'} = $ispatch;
$vars->{'isobsolete'} = $isobsolete;
$vars->{'isviewable'} = $isviewable;
$vars->{'statuses'} = \%statuses;
$vars->{'statusdefs'} = \@statusdefs;
$vars->{'attachments'} = \@bugattachments;
# Return the appropriate HTTP response headers.
print "Content-Type: text/html\n\n";
# Generate and return the UI (HTML page) from the appropriate template.
$template->process("attachment/edit.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
}
sub update
{
# Update an attachment record.
# Get the bug ID for the bug to which this attachment is attached.
SendSQL("SELECT bug_id FROM attachments WHERE attach_id = $::FORM{'id'}");
my $bugid = FetchSQLData()
|| DisplayError("Cannot figure out bug number.")
&& exit;
# Lock database tables in preparation for updating the attachment.
if ($::driver eq 'mysql') {
SendSQL("LOCK TABLES attachments WRITE , attachstatuses WRITE ,
attachstatusdefs READ , fielddefs READ , bugs_activity WRITE");
}
# Get a copy of the attachment record before we make changes
# so we can record those changes in the activity table.
SendSQL("SELECT description, mimetype, ispatch, isobsolete
FROM attachments WHERE attach_id = $::FORM{'id'}");
my ($olddescription, $oldcontenttype, $oldispatch, $oldisobsolete) = FetchSQLData();
# Get the list of old status flags.
SendSQL("SELECT attachstatusdefs.name
FROM attachments, attachstatuses, attachstatusdefs
WHERE attachments.attach_id = $::FORM{'id'}
AND attachments.attach_id = attachstatuses.attach_id
AND attachstatuses.statusid = attachstatusdefs.id
ORDER BY attachstatusdefs.sortkey
");
my @oldstatuses;
while (MoreSQLData()) {
push(@oldstatuses, FetchSQLData());
}
my $oldstatuslist = join(', ', @oldstatuses);
# Update the database with the new status flags.
SendSQL("DELETE FROM attachstatuses WHERE attach_id = $::FORM{'id'}");
foreach my $statusid (@{$::MFORM{'status'}})
{
SendSQL("INSERT INTO attachstatuses (attach_id, statusid) VALUES ($::FORM{'id'}, $statusid)");
}
# Get the list of new status flags.
SendSQL("SELECT attachstatusdefs.name
FROM attachments, attachstatuses, attachstatusdefs
WHERE attachments.attach_id = $::FORM{'id'}
AND attachments.attach_id = attachstatuses.attach_id
AND attachstatuses.statusid = attachstatusdefs.id
ORDER BY attachstatusdefs.sortkey
");
my @newstatuses;
while (MoreSQLData()) {
push(@newstatuses, FetchSQLData());
}
my $newstatuslist = join(', ', @newstatuses);
# Quote the description and content type for use in the SQL UPDATE statement.
my $quoteddescription = SqlQuote($::FORM{'description'});
my $quotedcontenttype = SqlQuote($::FORM{'contenttype'});
# Update the attachment record in the database.
# Sets the creation timestamp to itself to avoid it being updated automatically.
SendSQL("UPDATE attachments
SET description = $quoteddescription ,
mimetype = $quotedcontenttype ,
ispatch = $::FORM{'ispatch'} ,
isobsolete = $::FORM{'isobsolete'} ,
creation_ts = creation_ts
WHERE attach_id = $::FORM{'id'}
");
# Record changes in the activity table.
if ($olddescription ne $::FORM{'description'}) {
my $quotedolddescription = SqlQuote($olddescription);
my $fieldid = GetFieldID('attachments.description');
SendSQL("INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
VALUES ($bugid, $::FORM{'id'}, $::userid, NOW(), $fieldid, $quotedolddescription, $quoteddescription)");
}
if ($oldcontenttype ne $::FORM{'contenttype'}) {
my $quotedoldcontenttype = SqlQuote($oldcontenttype);
my $fieldid = GetFieldID('attachments.mimetype');
SendSQL("INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
VALUES ($bugid, $::FORM{'id'}, $::userid, NOW(), $fieldid, $quotedoldcontenttype, $quotedcontenttype)");
}
if ($oldispatch ne $::FORM{'ispatch'}) {
my $fieldid = GetFieldID('attachments.ispatch');
SendSQL("INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
VALUES ($bugid, $::FORM{'id'}, $::userid, NOW(), $fieldid, $oldispatch, $::FORM{'ispatch'})");
}
if ($oldisobsolete ne $::FORM{'isobsolete'}) {
my $fieldid = GetFieldID('attachments.isobsolete');
SendSQL("INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
VALUES ($bugid, $::FORM{'id'}, $::userid, NOW(), $fieldid, $oldisobsolete, $::FORM{'isobsolete'})");
}
if ($oldstatuslist ne $newstatuslist) {
my ($removed, $added) = DiffStrings($oldstatuslist, $newstatuslist);
my $quotedremoved = SqlQuote($removed);
my $quotedadded = SqlQuote($added);
my $fieldid = GetFieldID('attachstatusdefs.name');
SendSQL("INSERT INTO bugs_activity (bug_id, attach_id, who, bug_when, fieldid, removed, added)
VALUES ($bugid, $::FORM{'id'}, $::userid, NOW(), $fieldid, $quotedremoved, $quotedadded)");
}
# Unlock all database tables now that we are finished updating the database.
if ($::driver eq 'mysql') {
SendSQL("UNLOCK TABLES");
}
# If this installation has enabled the request manager, let the manager know
# an attachment was updated so it can check for requests on that attachment
# and fulfill them. The request manager allows users to request database
# changes of other users and tracks the fulfillment of those requests. When
# an attachment record is updated and the request manager is called, it will
# fulfill those requests that were requested of the user performing the update
# which are requests for the attachment being updated.
#my $requests;
#if (Param('userequestmanager'))
#{
# use Request;
# # Specify the fieldnames that have been updated.
# my @fieldnames = ('description', 'mimetype', 'status', 'ispatch', 'isobsolete');
# # Fulfill pending requests.
# $requests = Request::fulfillRequest('attachment', $::FORM{'id'}, @fieldnames);
# $vars->{'requests'} = $requests;
#}
# If the user submitted a comment while editing the attachment,
# add the comment to the bug.
if ( $::FORM{'comment'} )
{
use Text::Wrap;
$Text::Wrap::columns = 80;
$Text::Wrap::huge = 'wrap';
# Append a string to the comment to let users know that the comment came from
# the "edit attachment" screen.
my $comment = qq|(From update of attachment $::FORM{'id'})\n| . $::FORM{'comment'};
my $wrappedcomment = "";
foreach my $line (split(/\r\n|\r|\n/, $comment))
{
if ( $line =~ /^>/ )
{
$wrappedcomment .= $line . "\n";
}
else
{
$wrappedcomment .= wrap('', '', $line) . "\n";
}
}
# Get the user's login name since the AppendComment function needs it.
my $who = DBID_to_name($::userid);
# Mention $::userid again so Perl doesn't give me a warning about it.
my $neverused = $::userid;
# Append the comment to the list of comments in the database.
AppendComment($bugid, $who, $wrappedcomment);
}
# Send mail to let people know the bug has changed. Uses a special syntax
# of the "open" and "exec" commands to capture the output of "processmail",
# which "system" doesn't allow, without running the command through a shell,
# which backticks (``) do.
#system ("./processmail", $bugid , $::userid);
#my $mailresults = `./processmail $bugid $::userid`;
my $mailresults = '';
open(PMAIL, "-|") or exec('./processmail', $bugid, DBID_to_name($::userid));
$mailresults .= $_ while <PMAIL>;
close(PMAIL);
# Define the variables and functions that will be passed to the UI template.
$vars->{'attachid'} = $::FORM{'id'};
$vars->{'bugid'} = $bugid;
$vars->{'mailresults'} = $mailresults;
# Return the appropriate HTTP response headers.
print "Content-Type: text/html\n\n";
# Generate and return the UI (HTML page) from the appropriate template.
$template->process("attachment/updated.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
}

View File

@@ -1,378 +0,0 @@
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# 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 the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Terry Weissman <terry@mozilla.org>
# Dave Miller <justdave@syndicomm.com>
use diagnostics;
use strict;
use RelationSet;
# Use the Attachment module to display attachments for the bug.
use Attachment;
sub show_bug {
# Shut up misguided -w warnings about "used only once". For some reason,
# "use vars" chokes on me when I try it here.
sub bug_form_pl_sillyness {
my $zz;
$zz = %::FORM;
$zz = %::proddesc;
$zz = %::prodmaxvotes;
$zz = @::enterable_products;
$zz = @::settable_resolution;
$zz = $::unconfirmedstate;
$zz = $::milestoneurl;
$zz = $::template;
$zz = $::vars;
$zz = @::legal_priority;
$zz = @::legal_platform;
$zz = @::legal_severity;
$zz = @::legal_bug_status;
$zz = @::target_milestone;
$zz = @::components;
$zz = @::legal_keywords;
$zz = @::versions;
$zz = @::legal_opsys;
}
# Use templates
my $template = $::template;
my $vars = $::vars;
$vars->{'GetBugLink'} = \&GetBugLink;
$vars->{'quoteUrls'} = \&quoteUrls,
$vars->{'lsearch'} = \&lsearch,
$vars->{'header_done'} = (@_),
quietly_check_login();
my $id = $::FORM{'id'};
if (!defined($id)) {
$template->process("bug/choose.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
exit;
}
my %user = %{$vars->{'user'}};
my %bug;
# Populate the bug hash with the info we get directly from the DB.
my $query = "
SELECT
bugs.bug_id,
product,
version,
rep_platform,
op_sys,
bug_status,
resolution,
priority,
bug_severity,
component,
assigned_to,
reporter,
bug_file_loc,
short_desc,
target_milestone,
qa_contact,
status_whiteboard, ";
if ($::driver eq 'mysql') {
$query .= "
date_format(creation_ts, '%Y-%m-%d %H:%i'),
groupset,
delta_ts, ";
} elsif ($::driver eq 'Pg') {
$query .= "
TO_CHAR(creation_ts, 'YYYY-MM-DD HH24:MI:SS'),
groupset,
TO_CHAR(delta_ts, 'YYYYMMDDHH24MISS'), ";
}
$query .= "
SUM(votes.count)
FROM
bugs LEFT JOIN votes USING(bug_id)
WHERE
bugs.bug_id = $id
GROUP BY
bugs.bug_id,
product,
version,
rep_platform,
op_sys,
bug_status,
resolution,
priority,
bug_severity,
component,
assigned_to,
reporter,
bug_file_loc,
short_desc,
target_milestone,
qa_contact,
status_whiteboard,
creation_ts,
groupset,
delta_ts ";
SendSQL($query);
my $value;
my @row = FetchSQLData();
foreach my $field ("bug_id", "product", "version", "rep_platform",
"op_sys", "bug_status", "resolution", "priority",
"bug_severity", "component", "assigned_to", "reporter",
"bug_file_loc", "short_desc", "target_milestone",
"qa_contact", "status_whiteboard", "creation_ts",
"groupset", "delta_ts", "votes")
{
$value = shift(@row);
$bug{$field} = defined($value) ? $value : "";
}
# General arrays of info about the database state
GetVersionTable();
# Fiddle the product list.
my $seen_curr_prod;
my @prodlist;
foreach my $product (@::enterable_products) {
if ($product eq $bug{'product'}) {
# if it's the product the bug is already in, it's ALWAYS in
# the popup, period, whether the user can see it or not, and
# regardless of the disallownew setting.
$seen_curr_prod = 1;
push(@prodlist, $product);
next;
}
if (Param("usebuggroupsentry")
&& GroupExists($product)
&& !UserInGroup($product))
{
# If we're using bug groups to restrict entry on products, and
# this product has a bug group, and the user is not in that
# group, we don't want to include that product in this list.
next;
}
push(@prodlist, $product);
}
# The current product is part of the popup, even if new bugs are no longer
# allowed for that product
if (!$seen_curr_prod) {
push (@prodlist, $bug{'product'});
@prodlist = sort @prodlist;
}
$vars->{'product'} = \@prodlist;
$vars->{'rep_platform'} = \@::legal_platform;
$vars->{'priority'} = \@::legal_priority;
$vars->{'bug_severity'} = \@::legal_severity;
$vars->{'op_sys'} = \@::legal_opsys;
$vars->{'bug_status'} = \@::legal_bug_status;
# Hack - this array contains "" for some reason. See bug 106589.
shift @::settable_resolution;
$vars->{'resolution'} = \@::settable_resolution;
$vars->{'component_'} = $::components{$bug{'product'}};
$vars->{'version'} = $::versions{$bug{'product'}};
$vars->{'target_milestone'} = $::target_milestone{$bug{'product'}};
$bug{'milestoneurl'} = $::milestoneurl{$bug{'product'}} ||
"notargetmilestone.html";
$vars->{'use_votes'} = $::prodmaxvotes{$bug{'product'}};
# Add additional, calculated fields to the bug hash
if (@::legal_keywords) {
$vars->{'use_keywords'} = 1;
SendSQL("SELECT keyworddefs.name
FROM keyworddefs, keywords
WHERE keywords.bug_id = $id
AND keyworddefs.id = keywords.keywordid
ORDER BY keyworddefs.name");
my @keywords;
while (MoreSQLData()) {
push(@keywords, FetchOneColumn());
}
$bug{'keywords'} = \@keywords;
}
# Attachments
$bug{'attachments'} = Attachment::query($id);
# Dependencies
my @list;
SendSQL("SELECT dependson FROM dependencies WHERE
blocked = $id ORDER BY dependson");
while (MoreSQLData()) {
my ($i) = FetchSQLData();
push(@list, $i);
}
$bug{'dependson'} = \@list;
my @list2;
SendSQL("SELECT blocked FROM dependencies WHERE
dependson = $id ORDER BY blocked");
while (MoreSQLData()) {
my ($i) = FetchSQLData();
push(@list2, $i);
}
$bug{'blocked'} = \@list2;
# Groups
my @groups;
if ($::usergroupset ne '0' || $bug{'groupset'} ne '0') {
my $bug_groupset = $bug{'groupset'};
if ($::driver eq 'mysql') {
SendSQL("select bit, name, description, (bit & $bug{'groupset'} != 0), " .
"(bit & $::usergroupset != 0) from groups where isbuggroup != 0 " .
# Include active groups as well as inactive groups to which
# the bug already belongs. This way the bug can be removed
# from an inactive group but can only be added to active ones.
"and ((isactive = 1 or (bit & $bug{'groupset'} != 0)) or " .
"(bit & $bug{'groupset'} != 0)) " .
"order by description");
} elsif ($::driver eq 'Pg') {
SendSQL("select group_bit, name, description, (group_bit & int8($bug{'groupset'}) != 0), " .
"(group_bit & int8($::usergroupset) != 0) from groups where isbuggroup != 0 " .
# Include active groups as well as inactive groups to which
# the bug already belongs. This way the bug can be removed
# from an inactive group but can only be added to active ones.
"and ((isactive = 1 or (group_bit & int8($bug{'groupset'}) != 0)) or " .
"(group_bit & int8($bug{'groupset'}) != 0)) " .
"order by description");
}
$user{'inallgroups'} = 1;
while (MoreSQLData()) {
my ($bit, $name, $description, $ison, $ingroup) = FetchSQLData();
# For product groups, we only want to display the checkbox if either
# (1) The bit is already set, or
# (2) The user is in the group, but either:
# (a) The group is a product group for the current product, or
# (b) The group name isn't a product name
# This means that all product groups will be skipped, but
# non-product bug groups will still be displayed.
if($ison ||
($ingroup && (($name eq $bug{'product'}) ||
(!defined $::proddesc{$name}))))
{
$user{'inallgroups'} &= $ingroup;
push (@groups, { "bit" => $bit,
"ison" => $ison,
"ingroup" => $ingroup,
"description" => $description });
}
}
# If the bug is restricted to a group, display checkboxes that allow
# the user to set whether or not the reporter
# and cc list can see the bug even if they are not members of all
# groups to which the bug is restricted.
if ($bug{'groupset'} != 0) {
$bug{'inagroup'} = 1;
# Determine whether or not the bug is always accessible by the
# reporter, QA contact, and/or users on the cc: list.
SendSQL("SELECT reporter_accessible, cclist_accessible
FROM bugs
WHERE bug_id = $id
");
($bug{'reporter_accessible'},
$bug{'cclist_accessible'}) = FetchSQLData();
}
}
$vars->{'groups'} = \@groups;
my $movers = Param("movers");
$user{'canmove'} = Param("move-enabled")
&& (defined $::COOKIE{"Bugzilla_login"})
&& ($::COOKIE{"Bugzilla_login"} =~ /\Q$movers\E/);
# User permissions
# In the below, if the person hasn't logged in ($::userid == 0), then
# we treat them as if they can do anything. That's because we don't
# know why they haven't logged in; it may just be because they don't
# use cookies. Display everything as if they have all the permissions
# in the world; their permissions will get checked when they log in
# and actually try to make the change.
$user{'canedit'} = $::userid == 0
|| $::userid == $bug{'reporter'}
|| $::userid == $bug{'qa_contact'}
|| $::userid == $bug{'assigned_to'}
|| UserInGroup("editbugs");
$user{'canconfirm'} = ($::userid == 0) || UserInGroup("canconfirm");
# Bug states
$bug{'isunconfirmed'} = ($bug{'bug_status'} eq $::unconfirmedstate);
$bug{'isopened'} = IsOpenedState($bug{'bug_status'});
# People involved with the bug
$bug{'assigned_to_email'} = DBID_to_name($bug{'assigned_to'});
$bug{'assigned_to'} = DBID_to_real_or_loginname($bug{'assigned_to'});
$bug{'reporter'} = DBID_to_real_or_loginname($bug{'reporter'});
$bug{'qa_contact'} = $bug{'qa_contact'} > 0 ?
DBID_to_name($bug{'qa_contact'}) : "";
my $ccset = new RelationSet;
$ccset->mergeFromDB("SELECT who FROM cc WHERE bug_id=$id");
my @cc = $ccset->toArrayOfStrings();
$bug{'cc'} = \@cc if $cc[0];
# Next bug in list (if there is one)
my @bug_list;
if ($::COOKIE{"BUGLIST"} && $id)
{
@bug_list = split(/:/, $::COOKIE{"BUGLIST"});
}
$vars->{'bug_list'} = \@bug_list;
$bug{'comments'} = GetComments($bug{'bug_id'});
# This is length in number of comments
$bug{'longdesclength'} = scalar(@{$bug{'comments'}});
# Add the bug and user hashes to the variables
$vars->{'bug'} = \%bug;
$vars->{'user'} = \%user;
# Generate and return the UI (HTML page) from the appropriate template.
$template->process("bug/edit.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
}
1;

View File

@@ -1,206 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<!--
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 the Bugzilla Bug Tracking System.
The Initial Developer of the Original Code is Netscape Communications
Corporation. Portions created by Netscape are
Copyright (C) 1998 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s):
Contributor(s): Terry Weissman <terry@mozilla.org>
-->
<head>
<TITLE>A Bug's Life Cycle</TITLE>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body>
<h1 ALIGN=CENTER>A Bug's Life Cycle</h1>
The <B>status</B> and <B>resolution</B> field define and track the
life cycle of a bug.
<a name="status"></a>
<p>
<TABLE BORDER=1 CELLPADDING=4>
<TR ALIGN=CENTER VALIGN=TOP>
<TD WIDTH="50%"><H1>STATUS</H1> <TD><H1>RESOLUTION</H1>
<TR VALIGN=TOP>
<TD>The <B>status</B> field indicates the general health of a bug. Only
certain status transitions are allowed.
<TD>The <b>resolution</b> field indicates what happened to this bug.
<TR VALIGN=TOP><TD>
<DL><DT><B>
<A HREF="confirmhelp.html">UNCONFIRMED</A></B>
<DD> This bug has recently been added to the database. Nobody has
validated that this bug is true. Users who have the "canconfirm"
permission set may confirm this bug, changing its state to NEW.
Or, it may be directly resolved and marked RESOLVED.
<DT><B>NEW</B>
<DD> This bug has recently been added to the assignee's list of bugs
and must be processed. Bugs in this state may be accepted, and
become <B>ASSIGNED</B>, passed on to someone else, and remain
<B>NEW</B>, or resolved and marked <B>RESOLVED</B>.
<DT><B>ASSIGNED</B>
<DD> This bug is not yet resolved, but is assigned to the proper
person. From here bugs can be given to another person and become
<B>NEW</B>, or resolved and become <B>RESOLVED</B>.
<DT><B>REOPENED</B>
<DD>This bug was once resolved, but the resolution was deemed
incorrect. For example, a <B>WORKSFORME</B> bug is
<B>REOPENED</B> when more information shows up and the bug is now
reproducible. From here bugs are either marked <B>ASSIGNED</B>
or <B>RESOLVED</B>.
</DL>
<TD>
<DL>
<DD> No resolution yet. All bugs which are in one of these "open" states
have the resolution set to blank. All other bugs
will be marked with one of the following resolutions.
</DL>
<TR VALIGN=TOP><TD>
<DL>
<DT><B>RESOLVED</B>
<DD> A resolution has been taken, and it is awaiting verification by
QA. From here bugs are either re-opened and become
<B>REOPENED</B>, are marked <B>VERIFIED</B>, or are closed for good
and marked <B>CLOSED</B>.
<DT><B>VERIFIED</B>
<DD> QA has looked at the bug and the resolution and agrees that the
appropriate resolution has been taken. Bugs remain in this state
until the product they were reported against actually ships, at
which point they become <B>CLOSED</B>.
<DT><B>CLOSED</B>
<DD> The bug is considered dead, the resolution is correct. Any zombie
bugs who choose to walk the earth again must do so by becoming
<B>REOPENED</B>.
</DL>
<TD>
<DL>
<DT><B>FIXED</B>
<DD> A fix for this bug is checked into the tree and tested.
<DT><B>INVALID</B>
<DD> The problem described is not a bug
<DT><B>WONTFIX</B>
<DD> The problem described is a bug which will never be fixed.
<DT><B>LATER</B>
<DD> The problem described is a bug which will not be fixed in this
version of the product.
<DT><B>REMIND</B>
<DD> The problem described is a bug which will probably not be fixed in this
version of the product, but might still be.
<DT><B>DUPLICATE</B>
<DD> The problem is a duplicate of an existing bug. Marking a bug
duplicate requires the bug# of the duplicating bug and will at
least put that bug number in the description field.
<DT><B>WORKSFORME</B>
<DD> All attempts at reproducing this bug were futile, reading the
code produces no clues as to why this behavior would occur. If
more information appears later, please re-assign the bug, for
now, file it.
</DL>
</TABLE>
<H1>Other Fields</H1>
<table border=1 cellpadding=4><tr><td>
<h2><a name="severity">Severity</a></h2>
This field describes the impact of a bug.
<p>
<p>
<table>
<tr><th>Blocker</th><td>Blocks development and/or testing work
<tr><th>Critical</th><td>crashes, loss of data, severe memory leak
<tr><th>Major</th><td>major loss of function
<tr><th>Minor</th><td>minor loss of function, or other problem where easy workaround is present
<tr><th>Trivial</th><td>cosmetic problem like misspelled words or misaligned text
<tr><th>Enhancement</th><td>Request for enhancement
</table>
</td><td>
<h2><a name="priority">Priority</a></h2>
This field describes the importance and order in which a bug should be
fixed. This field is utilized by the programmers/engineers to
prioritize their work to be done. The available priorities are:
<p>
<p>
<table>
<tr><th>P1</th><td>Most important
<tr><th>P2</th><td>
<tr><th>P3</th><td>
<tr><th>P4</th><td>
<tr><th>P5</th><td>Least important
</table>
</tr></table>
<h2><a name="rep_platform">Platform</a></h2>
This is the hardware platform against which the bug was reported. Legal
platforms include:
<UL>
<LI> All (happens on all platform; cross-platform bug)
<LI> Macintosh
<LI> PC
<LI> Sun
<LI> HP
</UL>
<b>Note:</b> Selecting the option "All" does not select bugs assigned against all platforms. It
merely selects bugs that <b>occur</b> on all platforms.
<h2><a name="op_sys">Operating System</a></h2>
This is the operating system against which the bug was reported. Legal
operating systems include:
<UL>
<LI> All (happens on all operating systems; cross-platform bug)
<LI> Windows 95
<LI> Mac System 8.0
<LI> Linux
</UL>
Note that the operating system implies the platform, but not always.
For example, Linux can run on PC and Macintosh and others.
<h2><a name="assigned_to">Assigned To</a></h2>
This is the person in charge of resolving the bug. Every time this
field changes, the status changes to <B>NEW</B> to make it easy to see
which new bugs have appeared on a person's list.
The default status for queries is set to NEW, ASSIGNED and REOPENED. When
searching for bugs that have been resolved or verified, remember to set the
status field appropriately.
<hr>
<!-- hhmts start -->
Last modified: Sun Apr 14 12:51:23 EST 2002
<!-- hhmts end -->
</body> </html>

File diff suppressed because it is too large Load Diff

View File

@@ -1,392 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<title>Bug Writing Guidelines</title>
</head>
<body>
<center>
<h1>Bug Writing Guidelines</h1>
</center>
<h3>Why You Should Read This</h3>
<blockquote>
<p>Simply put, the more effectively you report a bug, the more
likely an engineer will actually fix it.</p>
<p>These guidelines are a general
tutorial to teach novice and intermediate bug reporters how to compose effective bug reports. Not every sentence may precisely apply to
your software project.</p>
</blockquote>
<h3>How to Write a Useful Bug Report</h3>
<blockquote>
<p>Useful bug reports are ones that get bugs fixed. A useful bug
report normally has two qualities:</p>
<ol>
<li><b>Reproducible.</b> If an engineer can't see the bug herself to prove that it exists, she'll probably stamp your bug report "WORKSFORME" or "INVALID" and move on to the next bug. Every detail you can provide helps.<br>
<br>
</li>
<li><b>Specific.</b> The quicker the engineer can isolate the bug
to a specific area, the more likely she'll expediently fix it.
(If a programmer or tester has to decypher a bug, they may spend
more time cursing the submitter than solving the problem.)
<br>
<br>
[ <a href="#tips" name="Anchor">Tell Me More</a> ]
</li>
</ol>
<p>Let's say the application you're testing is a web browser. You
crash at foo.com, and want to write up a bug report:</p>
<blockquote>
<p><b>BAD:</b> "My browser crashed. I think I was on www.foo.com. I play golf with Bill Gates, so you better fix this problem, or I'll report you to him. By the way, your Back icon looks like a squashed rodent. UGGGLY. And my grandmother's home page is all messed up in your browser. Thx 4 UR help."
</p>
<p>
<b>GOOD:</b> "I crashed each time I went to www.foo.com, using
the 2002-02-25 build on a Windows 2000 system. I also
rebooted into Linux, and reproduced this problem using the 2002-02-24
Linux build.
</p>
<p>
It again crashed each time upon drawing the Foo banner at the top
of the page. I broke apart the page, and discovered that the
following image link will crash the application reproducibly,
unless you remove the "border=0" attribute:
</p>
<p>
<tt>&lt;IMG SRC="http://www.foo.com/images/topics/topicfoos.gif"
width="34" height="44" border="0" alt="News"&gt;</tt>
</p>
</blockquote>
</blockquote>
<h3>How to Enter your Useful Bug Report into Bugzilla:</h3>
<blockquote>
<p>Before you enter your bug, use Bugzilla's
<a href="query.cgi">search page</a> to determine whether the defect you've discovered is a known, already-reported bug. If your bug is the 37th duplicate of a known issue, you're more likely to annoy the engineer. (Annoyed
engineers fix fewer bugs.)
</p>
<p>
Next, be sure to reproduce your bug using a recent
build. Engineers tend to be most interested in problems affecting
the code base that they're actively working on. After all, the bug you're reporting
may already be fixed.
</p>
<p>
If you've discovered a new bug using a current build, report it in
Bugzilla:
</p>
<ol>
<li>From your Bugzilla main page, choose
"<a href="enter_bug.cgi">Enter a new bug</a>".</li>
<li>Select the product that you've found a bug in.</li>
<li>Enter your e-mail address, password, and press the "Login"
button. (If you don't yet have a password, leave the password field empty,
and press the "E-mail me a password" button instead.
You'll quickly receive an e-mail message with your password.)</li>
</ol>
<p>Now, fill out the form. Here's what it all means:</p>
<p><b>Where did you find the bug?</b></p>
<blockquote>
<p><b>Product: In which product did you find the bug?</b><br>
You just specified this on the last page, so you can't edit it here.</p>
<p><b>Version: In which product version did you find the
bug?</b><br>
(If applicable)</p>
<p><b>Component: In which component does the bug exist?</b><br>
Bugzilla requires that you select a component to enter a bug. (Not sure which to choose?
Click on the Component link. You'll see a description of each component, to help you make the best choice.)</p>
<p><b>OS: On which Operating System (OS) did you find this bug?</b>
(e.g. Linux, Windows 2000, Mac OS 9.)<br>
If you know the bug happens on all OSs, choose 'All'. Otherwise,
select the OS that you found the bug on, or "Other" if your OS
isn't listed.</p>
</blockquote>
<p><b>How important is the bug?</b></p>
<blockquote>
<p><b>Severity: How damaging is the bug?</b><br>
This item defaults to 'normal'. If you're not sure what severity your bug deserves, click on the Severity link.
You'll see a description of each severity rating. <br>
</p>
</blockquote>
<p><b>Who will be following up on the bug?</b></p>
<blockquote>
<p><b>Assigned To: Which engineer should be responsible for fixing
this bug?</b><br>
Bugzilla will automatically assign the bug to a default engineer
upon submitting a bug report. If you'd prefer to directly assign the bug to
someone else, enter their e-mail address into this field. (To see the list of
default engineers for each component, click on the Component
link.)</p>
<p><b>Cc: Who else should receive e-mail updates on changes to this
bug?</b><br>
List the full e-mail addresses of other individuals who should
receive an e-mail update upon every change to the bug report. You
can enter as many e-mail addresses as you'd like, separated by spaces or commas, as long as those
people have Bugzilla accounts.</p>
</blockquote>
<p><b>What else can you tell the engineer about the bug?</b></p>
<blockquote>
<p><b>Summary:</b> <b>How would you describe the bug, in
approximately 60 or fewer characters?</b><br>
A good summary should <b>quickly and uniquely identify a bug
report</b>. Otherwise, an engineer cannot meaningfully identify
your bug by its summary, and will often fail to pay attention to
your bug report when skimming through a 10 page bug list.<br>
<br>
A useful summary might be
"<tt>PCMCIA install fails on Tosh Tecra 780DVD w/ 3c589C</tt>".
"<tt>Software fails</tt>" or "<tt>install problem</tt>" would be
examples of a bad summary.<br>
<br>
[ <a href="#summary">Tell Me More</a> ]<br>
<br>
<b>Description: </b><br>
Please provide a detailed problem report in this field.
Your bug's recipients will most likely expect the following information:</p>
<blockquote>
<p><b>Overview Description:</b> More detailed expansion of
summary.</p>
<blockquote>
<pre>
Drag-selecting any page crashes Mac builds in NSGetFactory
</pre>
</blockquote>
<p><b>Steps to Reproduce:</b> Minimized, easy-to-follow steps that will
trigger the bug. Include any special setup steps.</p>
<blockquote>
<pre>
1) View any web page. (I used the default sample page,
resource:/res/samples/test0.html)
2) Drag-select the page. (Specifically, while holding down
the mouse button, drag the mouse pointer downwards from any
point in the browser's content region to the bottom of the
browser's content region.)
</pre>
</blockquote>
<p>
<b>Actual Results:</b> What the application did after performing
the above steps.
</p>
<blockquote>
<pre>
The application crashed. Stack crawl appended below from MacsBug.
</pre>
</blockquote>
<p><b>Expected Results:</b> What the application should have done,
were the bug not present.</p>
<blockquote>
<pre>
The window should scroll downwards. Scrolled content should be selected.
(Or, at least, the application should not crash.)
</pre>
</blockquote>
<p><b>Build Date &amp; Platform:</b> Date and platform of the build
that you first encountered the bug in.</p>
<blockquote>
<pre>
Build 2002-03-15 on Mac OS 9.0
</pre>
</blockquote>
<p><b>Additional Builds and Platforms:</b> Whether or not the bug
takes place on other platforms (or browsers, if applicable).</p>
<blockquote>
<pre>
- Also Occurs On
Mozilla (2002-03-15 build on Windows NT 4.0)
- Doesn't Occur On
Mozilla (2002-03-15 build on Red Hat Linux; feature not supported)
Internet Explorer 5.0 (shipping build on Windows NT 4.0)
Netscape Communicator 4.5 (shipping build on Mac OS 9.0)
</pre>
</blockquote>
<p><b>Additional Information:</b> Any other debugging information.
For crashing bugs:</p>
<ul>
<li><b>Win32:</b> if you receive a Dr. Watson error, please note
the type of the crash, and the module that the application crashed
in. (e.g. access violation in apprunner.exe)</li>
<li><b>Mac OS:</b> if you're running MacsBug, please provide the
results of a <b>how</b> and an <b>sc</b>:</li>
</ul>
<blockquote>
<pre>
*** MACSBUG STACK CRAWL OF CRASH (Mac OS)
Calling chain using A6/R1 links
Back chain ISA Caller
00000000 PPC 0BA85E74
03AEFD80 PPC 0B742248
03AEFD30 PPC 0B50FDDC NSGetFactory+027FC
PowerPC unmapped memory exception at 0B512BD0 NSGetFactory+055F0
</pre>
</blockquote>
</blockquote>
</blockquote>
<p>You're done!<br>
<br>
After double-checking your entries for any possible errors, press
the "Commit" button, and your bug report will now be in the
Bugzilla database.<br>
</p>
</blockquote>
<hr>
<h3>More Information on Writing Good Bugs</h3>
<blockquote>
<p><b><a name="tips"></a> 1. General Tips for a Useful Bug
Report</b>
</p>
<blockquote>
<p>
<b>Use an explicit structure, so your bug reports are easy to
skim.</b> Bug report users often need immediate access to specific
sections of your bug. If your Bugzilla installation supports the
Bugzilla Helper, use it.
</p>
<p>
<b>Avoid cuteness if it costs clarity.</b> Nobody will be laughing
at your funny bug title at 3:00 AM when they can't remember how to
find your bug.
</p>
<p>
<b>One bug per report.</b> Completely different people typically
fix, verify, and prioritize different bugs. If you mix a handful of
bugs into a single report, the right people probably won't discover
your bugs in a timely fashion, or at all. Certain bugs are also
more important than others. It's impossible to prioritize a bug
report when it contains four different issues, all of differing
importance.
</p>
<p>
<b>No bug is too trivial to report.</b> Unless you're reading the
source code, you can't see actual software bugs, like a dangling
pointer -- you'll see their visible manifestations, such as the
segfault when the application finally crashes. Severe software
problems can manifest themselves in superficially trivial ways.
File them anyway.<br>
</p>
</blockquote>
<p><b><a name="summary"></a>2. How and Why to Write Good Bug Summaries</b>
</p>
<blockquote>
<p><b>You want to make a good first impression on the bug
recipient.</b> Just like a New York Times headline guides readers
towards a relevant article from dozens of choices, will your bug summary
suggest that your bug report is worth reading from dozens or hundreds of
choices?
</p>
<p>
Conversely, a vague bug summary like <tt>install problem</tt> forces anyone
reviewing installation bugs to waste time opening up your bug to
determine whether it matters.
</p>
<p>
<b>Your bug will often be searched by its summary.</b> Just as
you'd find web pages with Google by searching by keywords through
intuition, so will other people locate your bugs. Descriptive bug
summaries are naturally keyword-rich, and easier to find.
</p>
<p>
For example, you'll find a bug titled "<tt>Dragging icons from List View to
gnome-terminal doesn't paste path</tt>" if you search on "List",
"terminal", or "path". Those search keywords wouldn't have found a
bug titled "<tt>Dragging icons
doesn't paste</tt>".
</p>
<p>
Ask yourself, "Would someone understand my bug from just this
summary?" If so, you've written a fine summary.
</p>
<p><b>Don't write titles like these:</b></p>
<ol>
<li>"Can't install" - Why can't you install? What happens when you
try to install?</li>
<li>"Severe Performance Problems" - ...and they occur when you do
what?</li>
<li>"back button does not work" - Ever? At all?</li>
</ol>
<p><b>Good bug titles:</b></p>
<ol>
<li>"1.0 upgrade installation fails if Mozilla M18 package present"
- Explains problem and the context.</li>
<li>"RPM 4 installer crashes if launched on Red Hat 6.2 (RPM 3)
system" - Explains what happens, and the context.</li>
</ol>
</blockquote>
</blockquote>
<p>(Written and maintained by
<a href="http://www.prometheus-music.com/eli">Eli Goldberg</a>. Claudius
Gayle, Gervase Markham, Peter Mock, Chris Pratt, Tom Schutter and Chris Yeh also
contributed significant changes. Constructive
<a href="mailto:eli@prometheus-music.com">suggestions</a> welcome.)</p>
</body>
</html>

View File

@@ -1,46 +0,0 @@
<!ELEMENT bugzilla (bug+)>
<!ATTLIST bugzilla
version CDATA #REQUIRED
urlbase CDATA #REQUIRED
maintainer CDATA #REQUIRED
exporter CDATA #IMPLIED
>
<!ELEMENT bug (bug_id, (bug_status, product, priority, version, rep_platform, assigned_to, delta_ts, component, reporter, target_milestone?, bug_severity, creation_ts, qa_contact?, op_sys, resolution?, bug_file_loc?, short_desc?, keywords*, status_whiteboard?, dependson*, blocks*, cc*, long_desc*, attachment*)?)>
<!ATTLIST bug
error (NotFound | NotPermitted | InvalidBugId) #IMPLIED
>
<!ELEMENT bug_id (#PCDATA)>
<!ELEMENT exporter (#PCDATA)>
<!ELEMENT urlbase (#PCDATA)>
<!ELEMENT bug_status (#PCDATA)>
<!ELEMENT product (#PCDATA)>
<!ELEMENT priority (#PCDATA)>
<!ELEMENT version (#PCDATA)>
<!ELEMENT rep_platform (#PCDATA)>
<!ELEMENT assigned_to (#PCDATA)>
<!ELEMENT delta_ts (#PCDATA)>
<!ELEMENT component (#PCDATA)>
<!ELEMENT reporter (#PCDATA)>
<!ELEMENT target_milestone (#PCDATA)>
<!ELEMENT bug_severity (#PCDATA)>
<!ELEMENT creation_ts (#PCDATA)>
<!ELEMENT qa_contact (#PCDATA)>
<!ELEMENT status_whiteboard (#PCDATA)>
<!ELEMENT op_sys (#PCDATA)>
<!ELEMENT resolution (#PCDATA)>
<!ELEMENT bug_file_loc (#PCDATA)>
<!ELEMENT short_desc (#PCDATA)>
<!ELEMENT keywords (#PCDATA)>
<!ELEMENT dependson (#PCDATA)>
<!ELEMENT blocks (#PCDATA)>
<!ELEMENT cc (#PCDATA)>
<!ELEMENT long_desc (who, bug_when, thetext)>
<!ELEMENT who (#PCDATA)>
<!ELEMENT bug_when (#PCDATA)>
<!ELEMENT thetext (#PCDATA)>
<!ELEMENT attachment (attachid, date, desc, type?, data?)>
<!ELEMENT attachid (#PCDATA)>
<!ELEMENT date (#PCDATA)>
<!ELEMENT desc (#PCDATA)>
<!ELEMENT type (#PCDATA)>
<!ELEMENT data (#PCDATA)>

View File

@@ -1,39 +0,0 @@
#!/usr/bonsaitools/bin/perl -wT
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# 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 the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Terry Weissman <terry@mozilla.org>
use strict;
print q{Content-type: text/html
<HTML>
<HEAD>
<META HTTP-EQUIV="Refresh"
CONTENT="0; URL=userprefs.cgi">
</HEAD>
<BODY>
This URL is obsolete. Forwarding you to the correct one.
<P>
Going to <A HREF="userprefs.cgi">userprefs.cgi</A>
<BR>
</BODY>
</HTML>
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,124 +0,0 @@
#!/usr/bonsaitools/bin/perl -wT
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# 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 the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Terry Weissman <terry@mozilla.org>
use diagnostics;
use strict;
use lib qw(.);
use vars qw(
@legal_keywords
$buffer
$template
$vars
);
require "CGI.pl";
print "Content-type: text/html\n";
# The master list not only says what fields are possible, but what order
# they get displayed in.
ConnectToDatabase();
GetVersionTable();
my @masterlist = ("opendate", "changeddate", "severity", "priority",
"platform", "owner", "reporter", "status", "resolution",
"product", "component", "version", "os", "votes");
if (Param("usetargetmilestone")) {
push(@masterlist, "target_milestone");
}
if (Param("useqacontact")) {
push(@masterlist, "qa_contact");
}
if (Param("usestatuswhiteboard")) {
push(@masterlist, "status_whiteboard");
}
if (@::legal_keywords) {
push(@masterlist, "keywords");
}
push(@masterlist, ("summary", "summaryfull"));
$vars->{masterlist} = \@masterlist;
my @collist;
if (defined $::FORM{'rememberedquery'}) {
my $splitheader = 0;
if (defined $::FORM{'resetit'}) {
@collist = @::default_column_list;
} else {
foreach my $i (@masterlist) {
if (defined $::FORM{"column_$i"}) {
push @collist, $i;
}
}
if (exists $::FORM{'splitheader'}) {
$splitheader = $::FORM{'splitheader'};
}
}
my $list = join(" ", @collist);
my $urlbase = Param("urlbase");
my $cookiepath = Param("cookiepath");
print "Set-Cookie: COLUMNLIST=$list ; path=$cookiepath ; expires=Sun, 30-Jun-2029 00:00:00 GMT\n";
print "Set-Cookie: SPLITHEADER=$::FORM{'splitheader'} ; path=$cookiepath ; expires=Sun, 30-Jun-2029 00:00:00 GMT\n";
print "Refresh: 0; URL=buglist.cgi?$::FORM{'rememberedquery'}\n";
print "\n";
print "<META HTTP-EQUIV=Refresh CONTENT=\"1; URL=$urlbase"."buglist.cgi?$::FORM{'rememberedquery'}\">\n";
print "<TITLE>What a hack.</TITLE>\n";
PutHeader ("Change columns");
print "Resubmitting your query with new columns...\n";
exit;
}
if (defined $::COOKIE{'COLUMNLIST'}) {
@collist = split(/ /, $::COOKIE{'COLUMNLIST'});
} else {
@collist = @::default_column_list;
}
$vars->{collist} = \@collist;
$vars->{splitheader} = 0;
if ($::COOKIE{'SPLITHEADER'}) {
$vars->{splitheader} = 1;
}
my %desc = ();
foreach my $i (@masterlist) {
$desc{$i} = $i;
}
$desc{'summary'} = "Summary (first 60 characters)";
$desc{'summaryfull'} = "Full Summary";
$vars->{desc} = \%desc;
$vars->{buffer} = $::buffer;
# Generate and return the UI (HTML page) from the appropriate template.
print "Content-type: text/html\n\n";
$template->process("list/change-columns.html.tmpl", $vars)
|| ThrowTemplateError($template->error());

View File

@@ -1,202 +0,0 @@
#!/usr/bonsaitools/bin/perl -w
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# 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 the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Terry Weissman <terry@mozilla.org>,
# Harrison Page <harrison@netscape.com>
# Gervase Markham <gerv@gerv.net>
# Run me out of cron at midnight to collect Bugzilla statistics.
use AnyDBM_File;
use diagnostics;
use strict;
use vars @::legal_product;
require "globals.pl";
# tidy up after graphing module
if (chdir("graphs")) {
unlink <./*.gif>;
unlink <./*.png>;
chdir("..");
}
ConnectToDatabase(1);
GetVersionTable();
my @myproducts;
push( @myproducts, "-All-", @::legal_product );
foreach (@myproducts) {
my $dir = "data/mining";
&check_data_dir ($dir);
&collect_stats ($dir, $_);
}
&calculate_dupes();
sub check_data_dir {
my $dir = shift;
if (! -d) {
mkdir $dir, 0777;
chmod 0777, $dir;
}
}
sub collect_stats {
my $dir = shift;
my $product = shift;
my $when = localtime (time);
# NB: Need to mangle the product for the filename, but use the real
# product name in the query
my $file_product = $product;
$file_product =~ s/\//-/gs;
my $file = join '/', $dir, $file_product;
my $exists = -f $file;
if (open DATA, ">>$file") {
push my @row, &today;
foreach my $status ('NEW', 'ASSIGNED', 'REOPENED', 'UNCONFIRMED', 'RESOLVED', 'VERIFIED', 'CLOSED') {
if( $product eq "-All-" ) {
SendSQL("select count(bug_status) from bugs where bug_status='$status'");
} else {
SendSQL("select count(bug_status) from bugs where bug_status='$status' and product='$product'");
}
push @row, FetchOneColumn();
}
foreach my $resolution ('FIXED', 'INVALID', 'WONTFIX', 'LATER', 'REMIND', 'DUPLICATE', 'WORKSFORME', 'MOVED') {
if( $product eq "-All-" ) {
SendSQL("select count(resolution) from bugs where resolution='$resolution'");
} else {
SendSQL("select count(resolution) from bugs where resolution='$resolution' and product='$product'");
}
push @row, FetchOneColumn();
}
if (! $exists) {
print DATA <<FIN;
# Bugzilla Daily Bug Stats
#
# Do not edit me! This file is generated.
#
# fields: DATE|NEW|ASSIGNED|REOPENED|UNCONFIRMED|RESOLVED|VERIFIED|CLOSED|FIXED|INVALID|WONTFIX|LATER|REMIND|DUPLICATE|WORKSFORME|MOVED
# Product: $product
# Created: $when
FIN
}
print DATA (join '|', @row) . "\n";
close DATA;
} else {
print "$0: $file, $!";
}
}
sub calculate_dupes {
SendSQL("SELECT * FROM duplicates");
my %dupes;
my %count;
my @row;
my $key;
my $changed = 1;
my $today = &today_dash;
# Save % count here in a date-named file
# so we can read it back in to do changed counters
# First, delete it if it exists, so we don't add to the contents of an old file
if (my @files = <data/duplicates/dupes$today*>) {
unlink @files;
}
dbmopen(%count, "data/duplicates/dupes$today", 0644) || die "Can't open DBM dupes file: $!";
# Create a hash with key "a bug number", value "bug which that bug is a
# direct dupe of" - straight from the duplicates table.
while (@row = FetchSQLData()) {
my $dupe_of = shift @row;
my $dupe = shift @row;
$dupes{$dupe} = $dupe_of;
}
# Total up the number of bugs which are dupes of a given bug
# count will then have key = "bug number",
# value = "number of immediate dupes of that bug".
foreach $key (keys(%dupes))
{
my $dupe_of = $dupes{$key};
if (!defined($count{$dupe_of})) {
$count{$dupe_of} = 0;
}
$count{$dupe_of}++;
}
# Now we collapse the dupe tree by iterating over %count until
# there is no further change.
while ($changed == 1)
{
$changed = 0;
foreach $key (keys(%count)) {
# if this bug is actually itself a dupe, and has a count...
if (defined($dupes{$key}) && $count{$key} > 0) {
# add that count onto the bug it is a dupe of,
# and zero the count; the check is to avoid
# loops
if ($count{$dupes{$key}} != 0) {
$count{$dupes{$key}} += $count{$key};
$count{$key} = 0;
$changed = 1;
}
}
}
}
# Remove the values for which the count is zero
foreach $key (keys(%count))
{
if ($count{$key} == 0) {
delete $count{$key};
}
}
dbmclose(%count);
}
sub today {
my ($dom, $mon, $year) = (localtime(time))[3, 4, 5];
return sprintf "%04d%02d%02d", 1900 + $year, ++$mon, $dom;
}
sub today_dash {
my ($dom, $mon, $year) = (localtime(time))[3, 4, 5];
return sprintf "%04d-%02d-%02d", 1900 + $year, ++$mon, $dom;
}

View File

@@ -1,168 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<!--
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 the Bugzilla Bug Tracking System.
The Initial Developer of the Original Code is Netscape Communications
Corporation. Portions created by Netscape are
Copyright (C) 2000 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s): Terry Weissman <terry@mozilla.org>
-->
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Understanding the UNCONFIRMED state, and other recent changes</title>
</head>
<body>
<h1>Understanding the UNCONFIRMED state, and other recent changes</h1>
<p>
[This document is aimed primarily at people who have used Bugzilla
before the UNCONFIRMED state was implemented. It might be helpful for
newer users as well.]
</p>
<p>
New bugs in some products will now show up in a new state,
UNCONFIRMED. This means that we have nobody has confirmed that the
bug is real. Very busy engineers will probably generally ignore
UNCONFIRMED that have been assigned to them, until they have been
confirmed in one way or another. (Engineers with more time will
hopefully glance over their UNCONFIRMED bugs regularly.)
</p>
<p>
The <a href="bug_status.html">page describing bug fields</a> has been
updated to include UNCONFIRMED.
</p>
<p>
There are two basic ways that a bug can become confirmed (and enter
the NEW) state.
</p>
<ul>
<li> A user with the appropriate permissions (see below for more on
permissions) decides that the bug is a valid one, and confirms
it. We hope to gather a small army of responsible volunteers
to regularly go through bugs for us.</li>
<li> The bug gathers a certain number of votes. <b>Any</b> valid Bugzilla user may vote for
bugs (each user gets a certain number of bugs); any UNCONFIRMED bug which
gets enough votes becomes automatically confirmed, and enters the NEW state.</li>
</ul>
<p>
One implication of this is that it is worth your time to search the
bug system for duplicates of your bug to vote on them, before
submitting your own bug. If we can spread around knowledge of this
fact, it ought to help cut down the number of duplicate bugs in the
system.
</p>
<h2>Permissions.</h2>
<p>
Users now have a certain set of permissions. To see your permissions,
check out the
<a href="userprefs.cgi?bank=permissions">user preferences</a> page.
</p>
<p>
If you have the "Can confirm a bug" permission, then you will be able
to move UNCONFIRMED bugs into the NEW state.
</p>
<p>
If you have the "Can edit all aspects of any bug" permission, then you
can tweak anything about any bug. If not, you may only edit those
bugs that you have submitted, or that you have assigned to you (or
qa-assigned to you). However, anyone may add a comment to any bug.
</p>
<p>
Some people (initially, the initial owners and initial qa-contacts for
components in the system) have the ability to give the above two
permissions to other people. So, if you really feel that you ought to
have one of these permissions, a good person to ask (via private
email, please!) is the person who is assigned a relevant bug.
</p>
<h2>Other details.</h2>
<p>
An initial stab was taken to decide who would be given which of the
above permissions. This was determined by some simple heurstics of
who was assigned bugs, and who the default owners of bugs were, and a
look at people who seem to have submitted several bugs that appear to
have been interesting and valid. Inevitably, we have failed to give
someone the permissions they deserve. Please don't take it
personally; just bear with us as we shake out the new system.
</p>
<p>
People with one of the two bits above can easily confirm their own
bugs, so bugs they submit will actually start out in the NEW state.
They can override this when submitting a bug.
</p>
<p>
People can ACCEPT or RESOLVE a bug assigned to them, even if they
aren't allowed to confirm it. However, the system remembers, and if
the bug gets REOPENED or reassigned to someone else, it will revert
back to the UNCONFIRMED state. If the bug has ever been confirmed,
then REOPENing or reassigning will cause it to go to the NEW or
REOPENED state.
</p>
<p>
Note that only some products support the UNCONFIRMED state. In other
products, all new bugs will automatically start in the NEW state.
</p>
<h2>Things still to be done.</h2>
<p>
There probably ought to be a way to get a bug back into the
UNCONFIRMED state, but there isn't yet.
</p>
<p>
If a person has submitted several bugs that get confirmed, then this
is probably a person who understands the system well, and deserves the
"Can confirm a bug" permission. This kind of person should be
detected and promoted automatically.
</p>
<p>
There should also be a way to automatically promote people to get the
"Can edit all aspects of any bug" permission.
</p>
<p>
The "enter a new bug" page needs to be revamped with easy ways for new
people to educate themselves on the benefit of searching for a bug
like the one they're about to submit and voting on it, rather than
adding a new useless duplicate.
</p>
<hr>
<p>
<!-- hhmts start -->
Last modified: Sun Apr 14 12:55:14 EST 2002
<!-- hhmts end -->
</p>
</body> </html>

View File

@@ -1,79 +0,0 @@
# -*- Mode: perl; indent-tabs-mode: nil -*-
# 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.
#
# This code is based on code found in bug_email.pl from the bugzilla
# email tracker. Initial contributors are ::
# Terry Weissman <terry@mozilla.org>
# Gregor Fischer <fischer@suse.de>
# Klaas Freitag <freitag@suse.de>
# Seth Landsman <seth@dworkin.net>
# The purpose of this module is to abstract out a bunch of the code
# that is central to email interfaces to bugzilla and its database
# Contributor : Seth Landsman <seth@dworkin.net>
# Initial checkin : 03/15/00 (SML)
# findUser() function moved from bug_email.pl to here
push @INC, "../."; # this script now lives in contrib
require "globals.pl";
use diagnostics;
use strict;
my $EMAIL_TRANSFORM_NONE = "email_transform_none";
my $EMAIL_TRANSFORM_BASE_DOMAIN = "email_transform_base_domain";
my $EMAIL_TRANSFORM_NAME_ONLY = "email_transform_name_only";
# change to do incoming email address fuzzy matching
my $email_transform = $EMAIL_TRANSFORM_NAME_ONLY;
# findUser()
# This function takes an email address and returns the user email.
# matching is sloppy based on the $email_transform parameter
sub findUser($) {
my ($address) = @_;
# if $email_transform is $EMAIL_TRANSFORM_NONE, return the address, otherwise, return undef
if ($email_transform eq $EMAIL_TRANSFORM_NONE) {
my $stmt = "SELECT login_name FROM profiles WHERE profiles.login_name = \'$address\';";
SendSQL($stmt);
my $found_address = FetchOneColumn();
return $found_address;
} elsif ($email_transform eq $EMAIL_TRANSFORM_BASE_DOMAIN) {
my ($username) = ($address =~ /(.+)@/);
my $stmt = "SELECT login_name FROM profiles WHERE profiles.login_name RLIKE \'$username\';";
SendSQL($stmt);
my $domain;
my $found = undef;
my $found_address;
my $new_address = undef;
while ((!$found) && ($found_address = FetchOneColumn())) {
($domain) = ($found_address =~ /.+@(.+)/);
if ($address =~ /$domain/) {
$found = 1;
$new_address = $found_address;
}
}
return $new_address;
} elsif ($email_transform eq $EMAIL_TRANSFORM_NAME_ONLY) {
my ($username) = ($address =~ /(.+)@/);
my $stmt = "SELECT login_name FROM profiles WHERE profiles.login_name RLIKE \'$username\';";
SendSQL($stmt);
my $found_address = FetchOneColumn();
return $found_address;
}
}
1;

View File

@@ -1,22 +0,0 @@
This directory contains contributed software related to Bugzilla.
Things in here have not necessarily been tested or tried by anyone
except the original contributor, so tred carefully. But it may still
be useful to you.
This directory includes:
mysqld-watcher.pl -- This script can be installed as a frequent cron
job to clean up stalled/dead queries.
gnats2bz.pl -- A perl script to help import bugs from a GNATS
database into a Bugzilla database. Contributed by
Tom Schutter <tom@platte.com>
bug_email.pl -- A perl script that can receive email containing
bug reports (email-interface). Contributed by
Klaas Freitag <freitag@SuSE.de>
README.Mailif -- Readme describing the mail interface.
bugmail_help.html -- User help page for the mail interface.
yp_nomail.sh -- Script you can run via cron that regularly updates
the nomail file for terminated employees

View File

@@ -1,80 +0,0 @@
The Bugzilla Mail interface
===========================
(UPDATE 03/14/00 to better reflect reality by SML)
The Bugzilla Mail interface allows to submit bugs to Bugzilla by email.
The Mail Interface Contribution consists of three files:
README.Mailif - this readme.
bug_email.pl - the script
bugmail_help.html - a user help html site
Installation:
Next is to add a user who receives the bugmails, e. g. bugmail. Create a
mail account and a home directory for the user.
The mailinterface script bug_email.pl needs to get the mail through stdin.
I use procmail for that, with the following line in the .procmailrc:
BUGZILLA_HOME=/usr/local/httpd/htdocs/bugzilla
:0 c
|(cd $BUGZILLA_HOME/contrib; ./bug_email.pl)
This defines the Bugzilla directory as the variable BUGZILLA_HOME and passes
all incoming mail to the script after cd'ing into the bugzilla home.
In some cases, it is necessary to alter the headers of incoming email. The
additional line to procmail :
:0 fhw
| formail -I "From " -a "From "
fixes many problems.
See bugzilla.procmailrc for a sample procmailrc that works for me (SML) and
also deals with bugzilla_email_append.pl
Customation:
There are some values inside the script which need to be customized for your
needs:
1. In sub-routine Reply (search 'sub Reply':
there is the line
print MAIL "From: Bugzilla Mailinterface<yourmail\@here.com>\n";
^^^^^^^^^^^^^^^^^^^^
Fill in your correct mail here. That will make it easy for people to reply
to the mail.
2. check, if your sendmail resides in /usr/sbin/sendmail, change the path if neccessary.
Search the script after 'default' - you find some default-Settings for bug
reports, which are used, if the sender did not send a field for it. The defaults
should be checked and changed.
Thats hopefully all, we will come up with any configuration file or something.
If your mail works, your script will insert mails from now on.
The mailinterface supports two commandline switches:
There are two command line switches :
-t: Testmode
The mailinterface does not really insert the bug into the database, but
writes some debug output to stdout and writes the mail into the file
bug_email_test.log in the data-dir.
-r: restricted mode
All lines before the first line with a keyword character are skipped.
In not restricted, default mode, these lines are added to the long
description of the bug.
02/2000 - Klaas Freitag, SuSE GmbH <freitag@suse.de>
03/2000 - Seth M. Landsman <seth@cs.brandeis.edu>
bug_email.pl now lives out of bugzilla/contrib
added line about formail

File diff suppressed because it is too large Load Diff

View File

@@ -1,223 +0,0 @@
<HTML>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<!--
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 the Bugzilla Bug Tracking System.
Contributor(s): Klaas Freitag <Freitag@SuSE.de>
-->
<HEAD> <TITLE>Bugzilla Mail Interface</TITLE> </HEAD>
<BODY BGCOLOR="#FFFFFF">
<CENTER><H1>The Bugzilla Mail Interface</H1>
Contributor: <A HREF="mailto:freitag@suse.de">Klaas Freitag</A>, SuSE GmbH
</CENTER>
<P>
The bugzilla Mail interface allows the registered bugzilla users to submit bugs by
sending email with a bug description. This is usefull for people, who do not work
inhouse and want to submitt bugs to the bugzilla system.
<p>
I know, show me the <A HREF="#examplemail">example-mail !</A>
<H2>What do you need to do to submitt a bug by mail ?</H2>
You need to send a email in the described format to the bugmail-user of the
bugzilla-system. This is <A HREF="mailto:our_bugzilla@xyz.com">yourbugzilla@here.com</A>
You receive a reply mail with the new bug-ID if your request was ok.
If not, you get a mail with
some help on the bugmail system and a specific analysis of your request.
<P>
Please dont refuse to send one or two wrong mails, you will get all the information
you need in the replies, and <I>only</I> in the mail replies. The information on this
page, concerning available products, versions and so on, is not dynamicly generated and
may be old therefore.
<H1>The Mail Format</H1>
The bugmail needs a special format , which consists of some keywords and suitable
values for them and a description text. Note that the keyword block needs to be
above of the description text.
<H2>Keywords</H2>
You need to tell bugzilla some properties of the bugs. This is done by keywords, which
start on a new line with a @, followed by the keyword and and equal-sign, followed by a
hopefully valid value.
<TABLE BORDER=4 FRAME=box CELLSPACING="5" width=95%> <COLGROUP> <col width="2*">
<col width="5*"> <col width="1*"> </COLGROUP>
<TR>
<TH>Keyword</TH>
<TH>Value description</TH>
<TH>required and default value</TH>
</TR>
<TR>
<TD>@product</TD>
<TD>The product which has a bug</TD>
<TD>yes. <br> This is the most important information. Many other
fields depend on the product.</TD>
</TR>
<TR>
<TD>@component</TD>
<TD>the desired component which is affected by the bug</TD>
<TD>yes. <br> As the @product, this is a very important
field.</TD>
</TR>
<TR>
<TD>@version</TD>
<TD>The version of the product</TD>
<TD>yes. <br>See @product and @component</TD>
</TR>
<TR>
<TD>@short_desc</TD>
<TD>A summary of your bug report</TD>
<TD>yes. <br>This summary of the error you want to report
describes what happen. You may skip the long description,
but not this summary.<br>
<b>Note:</b>The short description may be given in the mail subject
instead of using the keyword !</TD>
</TR>
<TR>
<TD>@rep_platform</TD>
<TD>The desired platform</TD>
<TD>no.<br>If you dont give a value, this field is set to <I>All</I>.</TD>
</TR>
<TR>
<TD>@bug_severity</TD>
<TD>The severity of the bug</TD>
<TD>no. <br> If you dont give a value, this field is set to
<I>normal</I></TD>
</TR>
<TR>
<TD>@priority</TD>
<TD>The priority of the bug</TD>
<TD>no.<br>If you dont give a value, this field is set to <I>P3</I></TD>
</TR>
<TR>
<TD>@op_sys</TD>
<TD>The operating system</TD>
<TD>no.<br>If you dont give a value, this field is set to <I>Linux</I>.</TD>
</TR>
<TR>
<TD>@assigned_to</TD>
<TD>The one to whom the bug is assigned to</TD>
<TD>no. <br>There is an initial owner for every product/version/component.
He owns the bug by default. The initial owner can only be found if
product, version and component are valid.</TD>
</TR>
<TR>
<TD>@bug_file_loc</TD>
<TD>?</TD>
<TD>no.</TD>
</TR>
<TR>
<TD>@status_whiteboard</TD>
<TD>?</TD>
<TD>no.</TD>
</TR>
<TR>
<TD>@target_milestone</TD>
<TD>?</TD>
<TD>no.</TD>
</TR>
<TR>
<TD>@groupset</TD>
<TD>rules the visibility of the bug.</TD>
<TD>no.<br>This value defaults to the smallest of the available groups,
which is <I>readInternal</I>.</TD>
</TR>
<TR>
<TD>@qa_contact</TD>
<TD>the quality manager for the product</TD>
<TD>no.<br>This value can be retrieved from product, component and
version</TD>
</TR>
</TABLE>
<H2>Valid values</H2>
Give string values for the most keys above. Some keywords require special values:<br>
<ol>
<li>E-Mail adresses: If you want to set the qa-contact, specify a email-adress for @qa_contact. The email must be known by bugzilla of course.</li>
<li>Listvalues: Most of the values have to be one of a list of valid values. Try by sending
a mail and read the reply. Skip fields if you dont get help for them unless you dont know
which values you may choose.</li>
<li>free Text: The descriptions may be free text. </li>
<li>Special: The field groupset may be specified in different in three different kinds:
<ol>
<li> A plain numeric way, which is one usually huge number, e. g. <I>65536</I></li>
<li> a string with added numbers e.g. <I>65536+131072</I></li>
<li> a string list, e.g. <I>ReadInternal, ReadBeta </I></li>
</ol>
</li>
</ol>
<p>
But most of them need <b>valid</b> values.
<p>
Sorry, you will not find lists of valid products, components and the other stuff
here. Send a mail to with any text, and you will get a list of valid keywords in the reply.
<p>
Some of the values must be choosen from a list:<br>
<ol>
<li>bug_severity: blocker, critical, major, normal, minor, trivial, enhancement</li>
<li>op_sys: Linux </li>
<li>priority: P1, P2, P3, P4, P5</li>
<li>rep_platform: All, i386, AXP, i686, Other</li></ol>
<p>
After you have specified the required keywords and maybe some other value, you may
describe your bug. You dont need a keyword for starting your bug description. All
text which follows the keyword block is handled as long description of the bug.
<p>
The bugmail interface is able to find required information by itself. E.g. if you specify
a product which has exactly one component, this component will be found by the interface
automatically.
<H1>Attachments</H1>
The mail interface is able to cope with MIME-attachments.
People could for example add a logfile as a mail attachment, and it will appear in
bugzilla as attachment. A comment for the attachment should be added, it will describe
the attachment in bugzilla.
<H1><A NAME="examplemail">Example Mail</A></H1>
See the example of the mail <b>body</b> (Dont forget to specify the short description
in the mail subject):<hr><pre>
@product = Bugzilla
@component = general
@version = All
@groupset = ReadWorld ReadPartners
@op_sys = Linux
@priority = P3
@rep_platform = i386
This is the description of the bug I found. It is not neccessary to start
it with a keyword.
Note: The short_description is neccessary and may be given with the keyword
@short_description or will be retrieved from the mail subject.
</pre><hr>
</BODY>
</HTML>

View File

@@ -1,30 +0,0 @@
:0 fhw
| formail -I "From " -a "From "
BUGZILLA_HOME=/home/bugzilla/WEB/bugzilla/contrib
:0
* ^Subject: .*\[Bug .*\]
RESULT=|(cd $BUGZILLA_HOME && ./bugzilla_email_append.pl)
# Feed mail to stdin of bug_email.pl
:0 Ec
#* !^Subject: .*[Bug .*]
RESULT=|(cd $BUGZILLA_HOME && ./bug_email.pl )
# write result to a logfile
:0 c
|echo `date '+%d.%m.%y %H:%M: '` $RESULT >> $HOME/bug_email.log
:0 c
|echo "----------------------------------" >> $HOME/bug_email.log
:0 c
$HOME/bug_email.log
# Move mail to the inbox
:0
$HOME/Mail/INBOX

View File

@@ -1,189 +0,0 @@
#!/usr/bin/perl -w
# -*- Mode: perl; indent-tabs-mode: nil -*-
# 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 purpose of this script is to take an email message, which
# specifies a bugid and append it to the bug as part of the longdesc
# table
# Contributor : Seth M. Landsman <seth@dworkin.net>
# 03/15/00 : Initial version by SML
# 03/15/00 : processmail gets called
# Email subject must be of format :
# .* Bug ### .*
# replying to a typical bugzilla email should be valid
# TODO :
# 1. better way to get the body text (I don't know what dump_entity() is
# actually doing
use diagnostics;
use strict;
use MIME::Parser;
push @INC, "../."; # this script lives in contrib
require "globals.pl";
require "BugzillaEmail.pm";
# Create a new MIME parser:
my $parser = new MIME::Parser;
my $Comment = "";
# Create and set the output directory:
# FIXME: There should be a $BUGZILLA_HOME variable (SML)
(-d "../data/mimedump-tmp") or mkdir "../data/mimedump-tmp",0755 or die "mkdir: $!";
(-w "../data/mimedump-tmp") or die "can't write to directory";
$parser->output_dir("../data/mimedump-tmp");
# Read the MIME message:
my $entity = $parser->read(\*STDIN) or die "couldn't parse MIME stream";
$entity->remove_sig(10); # Removes the signature in the last 10 lines
# Getting values from parsed mail
my $Sender = $entity->get( 'From' );
$Sender ||= $entity->get( 'Reply-To' );
my $Message_ID = $entity->get( 'Message-Id' );
die (" *** Cant find Sender-adress in sent mail ! ***\n" ) unless defined( $Sender );
chomp( $Sender );
chomp( $Message_ID );
print "Dealing with the sender $Sender\n";
ConnectToDatabase();
my $SenderShort = $Sender;
$SenderShort =~ s/^.*?([a-zA-Z0-9_.-]+?\@[a-zA-Z0-9_.-]+\.[a-zA-Z0-9_.-]+).*$/$1/;
$SenderShort = findUser($SenderShort);
print "SenderShort is $SenderShort\n";
if (!defined($SenderShort)) {
$SenderShort = $Sender;
$SenderShort =~ s/^.*?([a-zA-Z0-9_.-]+?\@[a-zA-Z0-9_.-]+\.[a-zA-Z0-9_.-]+).*$/$1/;
}
print "The sendershort is now $SenderShort\n";
if (!defined($SenderShort)) {
DealWithError("No such user $SenderShort exists.");
}
my $Subject = $entity->get('Subject');
print "The subject is $Subject\n";
my ($bugid) = ($Subject =~ /\[Bug ([\d]+)\]/);
print "The bugid is $bugid\n";
# make sure the bug exists
SendSQL("SELECT bug_id FROM bugs WHERE bug_id = $bugid;");
my $found_id = FetchOneColumn();
print "Did we find the bug? $found_id-\n";
if (!defined($found_id)) {
DealWithError("Bug $bugid does not exist");
}
# get the user id
SendSQL("SELECT userid FROM profiles WHERE login_name = \'$SenderShort\';");
my $userid = FetchOneColumn();
if (!defined($userid)) {
DealWithError("Userid not found for $SenderShort");
}
# parse out the text of the message
dump_entity($entity);
# Get rid of the bug id
$Subject =~ s/\[Bug [\d]+\]//;
#my $Comment = "This is only a test ...";
my $Body = "Subject: " . $Subject . "\n" . $Comment;
# shove it in the table
my $long_desc_query = "INSERT INTO longdescs SET bug_id=$found_id, who=$userid, bug_when=NOW(), thetext=" . SqlQuote($Body) . ";";
SendSQL($long_desc_query);
system("cd .. ; ./processmail $found_id '$SenderShort'");
sub DealWithError {
my ($reason) = @_;
print $reason . "\n";
}
# Yanking this wholesale from bug_email, 'cause I know this works. I'll
# figure out what it really does later
#------------------------------
#
# dump_entity ENTITY, NAME
#
# Recursive routine for parsing a mime coded mail.
# One mail may contain more than one mime blocks, which need to be
# handled. Therefore, this function is called recursively.
#
# It gets the for bugzilla important information from the mailbody and
# stores them into the global attachment-list @attachments. The attachment-list
# is needed in storeAttachments.
#
sub dump_entity {
my ($entity, $name) = @_;
defined($name) or $name = "'anonymous'";
my $IO;
# Output the body:
my @parts = $entity->parts;
if (@parts) { # multipart...
my $i;
foreach $i (0 .. $#parts) { # dump each part...
dump_entity($parts[$i], ("$name, part ".(1+$i)));
}
} else { # single part...
# Get MIME type, and display accordingly...
my $msg_part = $entity->head->get( 'Content-Disposition' );
$msg_part ||= "";
my ($type, $subtype) = split('/', $entity->head->mime_type);
my $body = $entity->bodyhandle;
my ($data, $on_disk );
if( $msg_part =~ /^attachment/ ) {
# Attached File
my $des = $entity->head->get('Content-Description');
$des ||= "";
if( defined( $body->path )) { # Data is on disk
$on_disk = 1;
$data = $body->path;
} else { # Data is in core
$on_disk = 0;
$data = $body->as_string;
}
# push ( @attachments, [ $data, $entity->head->mime_type, $on_disk, $des ] );
} else {
# Real Message
if ($type =~ /^(text|message)$/) { # text: display it...
if ($IO = $body->open("r")) {
$Comment .= $_ while (defined($_ = $IO->getline));
$IO->close;
} else { # d'oh!
print "$0: couldn't find/open '$name': $!";
}
} else { print "Oooops - no Body !\n"; }
}
}
}

View File

@@ -1,94 +0,0 @@
#!/bin/sh
# 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 the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is
# Andreas Franke <afranke@ags.uni-sb.de>.
# Corporation. Portions created by Andreas Franke are
# Copyright (C) 2001 Andreas Franke. All
# Rights Reserved.
#
# Contributor(s):
conf="`dirname $0`/query.conf"
query="http://bugzilla.mozilla.org/buglist.cgi?cmd=doit"
defaultcolumnlist="severity priority platform status resolution target_milestone status_whiteboard keywords summaryfull"
chart=0
and=0
while test "$1" != ""; do
arg=$1
arg_len=`expr length ${arg}`
if test `expr substr "${arg}" 1 2` == "--"; then
eq_pos=`expr match ${arg} '--.*='`
if test "${eq_pos}" == "0"; then
echo 'Missing value for long option '"${arg}"' ("=" not found)' 1>&2
exit 1;
fi
# extract option name
let name_len=${eq_pos}-3
name=`expr substr ${arg} 3 ${name_len}`
# extract option value
let val_start=${eq_pos}+1
let val_len=${arg_len}-${eq_pos}
val=`expr substr ${arg} ${val_start} ${val_len}`
elif test `expr substr ${arg} 1 1` == "-" &&
test "`expr substr ${arg} 2 1`" != ""; then
# extract
name=`expr substr ${arg} 2 1`
let val_len=${arg_len}-2
val=`expr substr ${arg} 3 ${val_len}`
else
name="default"
val="${arg}"
#echo "Unrecognized option ${arg}" 1>&2
#exit 1
fi
# find field and comparison type for option ${name}
field=`grep '"'${name}'"' ${conf} | awk '{printf $1}'`
type=`grep '"'${name}'"' ${conf} | awk '{printf $2}'`
if test "${field}" == "" || test "${type}" == ""; then
echo "Field name & comparison type not found for option ${name}." 1>&2
exit 1;
fi
or=0
while test "${val}" != ""; do
comma_idx=`expr index ${val} ,`
if test ${comma_idx} == "0"; then
val1="${val}"
val=""
else
let val1_len=${comma_idx}-1
val1=`expr substr ${val} 1 ${val1_len}`
val_len=`expr length ${val}`
let rest_start=${comma_idx}+1
let rest_len=${val_len}-${comma_idx}
val=`expr substr ${val} ${rest_start} ${rest_len}`
fi
query="${query}&field${chart}-${and}-${or}=${field}"
query="${query}&type${chart}-${and}-${or}=${type}"
query="${query}&value${chart}-${and}-${or}=${val1}"
#echo "----- ${name} : ${field} : ${type} : ${val1} -----" 1>&2
let or=${or}+1
done
let chart=${chart}+1
shift
done
outputfile="/dev/stdout"
#outputfile="buglist.html"
#\rm -f ${outputfile}
wget -q -O ${outputfile} --header="Cookie: COLUMNLIST=${COLUMNLIST-${defaultcolumnlist}}" "${query}"

View File

@@ -1,31 +0,0 @@
#!/bin/sh
# 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 the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is
# Andreas Franke <afranke@ags.uni-sb.de>.
# Corporation. Portions created by Andreas Franke are
# Copyright (C) 2001 Andreas Franke. All
# Rights Reserved.
#
# Contributor(s):
buglist="`dirname $0`/buglist"
htmlfile="`dirname $0`/buglist.html"
${buglist} "$@" 2>&1 1>${htmlfile}
if test ${?} == "0"; then
echo `grep 'TR VALIGN=TOP ALIGN=LEFT CLASS=' ${htmlfile} | sed -e 's/<TR.*id=//' | sed -e 's/".*//'` | sed -e 's/ /\,/g'
else
cat ${htmlfile} 1>&2
exit 1
fi

View File

@@ -1,49 +0,0 @@
# 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 the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is
# Andreas Franke <afranke@ags.uni-sb.de>.
# Corporation. Portions created by Andreas Franke are
# Copyright (C) 2001 Andreas Franke. All
# Rights Reserved.
#
# Contributor(s):
#
# This is `query.conf', the config file for `buglist'.
#
# Columns: 1: field_name, 2: comparison_type, 3: cmd-line options
#
bug_status substring "s","status"
resolution substring "r","resolution"
rep_platform substring "p","platform"
op_sys substring "o","os","opsys"
priority substring "p","priority"
bug_severity substring "S","severity"
assigned_to substring "A","O","owner","assignedto"
reporter substring "R","reporter"
qa_contact substring "Q","qa","qacontact"
cc substring "C","cc"
product substring "product"
version substring "V","version"
component substring "c","component"
target_milestone substring "M","milestone"
short_desc substring "default","summary"
longdesc substring "d","description","longdesc"
bug_file_loc substring "u","url"
status_whiteboard substring "w","whiteboard"
keywords substring "k","K","keywords"
attachments.description substring "attachdesc"
attachments.thedata substring "attachdata"
attachments.mimetype substring "attachmime"
dependson substring # bug 30823
blocked substring # bug 30823

View File

@@ -1,40 +0,0 @@
#!/bin/sh
#
# 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 the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Dawn Endico <endico@mozilla.org>
# Keep a record of all cvs updates made from a given directory.
#
# Later, if changes need to be backed out, look at the log file
# and run the cvs command with the date that you want to back
# out to. (Probably the second to last entry).
#DATE=`date +%e/%m/%Y\ %k:%M:%S\ %Z`
DATE=`date`
COMMAND="cvs update -d -P -D"
echo $COMMAND \"$DATE\" >> cvs-update.log
$COMMAND "$DATE"
# sample log file
#cvs update -P -D "11/04/2000 20:22:08 PDT"
#cvs update -P -D "11/05/2000 20:22:22 PDT"
#cvs update -P -D "11/07/2000 20:26:29 PDT"
#cvs update -P -D "11/08/2000 20:27:10 PDT"

File diff suppressed because it is too large Load Diff

View File

@@ -1,303 +0,0 @@
#!/usr/local/bin/python
# -*- mode: python -*-
"""
jb2bz.py - a nonce script to import bugs from JitterBug to Bugzilla
Written by Tom Emerson, tree@basistech.com
This script is provided in the hopes that it will be useful. No
rights reserved. No guarantees expressed or implied. Use at your own
risk. May be dangerous if swallowed. If it doesn't work for you, don't
blame me. It did what I needed it to do.
This code requires a recent version of Andy Dustman's MySQLdb interface,
http://sourceforge.net/projects/mysql-python
Share and enjoy.
"""
import rfc822, mimetools, multifile, mimetypes
import sys, re, glob, StringIO, os, stat, time
import MySQLdb, getopt
# mimetypes doesn't include everything we might encounter, yet.
if not mimetypes.types_map.has_key('.doc'):
mimetypes.types_map['.doc'] = 'application/msword'
if not mimetypes.encodings_map.has_key('.bz2'):
mimetypes.encodings_map['.bz2'] = "bzip2"
bug_status='NEW'
component="default"
version=""
product="" # this is required, the rest of these are defaulted as above
"""
Each bug in JitterBug is stored as a text file named by the bug number.
Additions to the bug are indicated by suffixes to this:
<bug>
<bug>.followup.*
<bug>.reply.*
<bug>.notes
The dates on the files represent the respective dates they were created/added.
All <bug>s and <bug>.reply.*s include RFC 822 mail headers. These could include
MIME file attachments as well that would need to be extracted.
There are other additions to the file names, such as
<bug>.notify
which are ignored.
Bugs in JitterBug are organized into directories. At Basis we used the following
naming conventions:
<product>-bugs Open bugs
<product>-requests Open Feature Requests
<product>-resolved Bugs/Features marked fixed by engineering, but not verified
<product>-verified Resolved defects that have been verified by QA
where <product> is either:
<product-name>
or
<product-name>-<version>
"""
def process_notes_file(current, fname):
try:
new_note = {}
notes = open(fname, "r")
s = os.fstat(notes.fileno())
new_note['text'] = notes.read()
new_note['timestamp'] = time.gmtime(s[stat.ST_MTIME])
notes.close()
current['notes'].append(new_note)
except IOError:
pass
def process_reply_file(current, fname):
new_note = {}
reply = open(fname, "r")
msg = rfc822.Message(reply)
new_note['text'] = "%s\n%s" % (msg['From'], msg.fp.read())
new_note['timestamp'] = rfc822.parsedate_tz(msg['Date'])
current["notes"].append(new_note)
def add_notes(current):
"""Add any notes that have been recorded for the current bug."""
process_notes_file(current, "%d.notes" % current['number'])
for f in glob.glob("%d.reply.*" % current['number']):
process_reply_file(current, f)
for f in glob.glob("%d.followup.*" % current['number']):
process_reply_file(current, f)
def maybe_add_attachment(current, file, submsg):
"""Adds the attachment to the current record"""
cd = submsg["Content-Disposition"]
m = re.search(r'filename="([^"]+)"', cd)
if m == None:
return
attachment_filename = m.group(1)
if (submsg.gettype() == 'application/octet-stream'):
# try get a more specific content-type for this attachment
type, encoding = mimetypes.guess_type(m.group(1))
if type == None:
type = submsg.gettype()
else:
type = submsg.gettype()
try:
data = StringIO.StringIO()
mimetools.decode(file, data, submsg.getencoding())
except:
return
current['attachments'].append( ( attachment_filename, type, data.getvalue() ) )
def process_mime_body(current, file, submsg):
data = StringIO.StringIO()
mimetools.decode(file, data, submsg.getencoding())
current['description'] = data.getvalue()
def process_text_plain(msg, current):
print "Processing: %d" % current['number']
current['description'] = msg.fp.read()
def process_multi_part(file, msg, current):
print "Processing: %d" % current['number']
mf = multifile.MultiFile(file)
mf.push(msg.getparam("boundary"))
while mf.next():
submsg = mimetools.Message(file)
if submsg.has_key("Content-Disposition"):
maybe_add_attachment(current, mf, submsg)
else:
# This is the message body itself (always?), so process
# accordingly
process_mime_body(current, mf, submsg)
def process_jitterbug(filename):
current = {}
current['number'] = int(filename)
current['notes'] = []
current['attachments'] = []
current['description'] = ''
current['date-reported'] = ()
current['short-description'] = ''
file = open(filename, "r")
msg = mimetools.Message(file)
msgtype = msg.gettype()
add_notes(current)
current['date-reported'] = rfc822.parsedate_tz(msg['Date'])
current['short-description'] = msg['Subject']
if msgtype[:5] == 'text/':
process_text_plain(msg, current)
elif msgtype[:10] == "multipart/":
process_multi_part(file, msg, current)
else:
# Huh? This should never happen.
print "Unknown content-type: %s" % msgtype
sys.exit(1)
# At this point we have processed the message: we have all of the notes and
# attachments stored, so it's time to add things to the database.
# The schema for JitterBug 2.14 can be found at:
#
# http://www.trilobyte.net/barnsons/html/dbschema.html
#
# The following fields need to be provided by the user:
#
# bug_status
# product
# version
# reporter
# component
# resolution
# change this to the user_id of the Bugzilla user who is blessed with the
# imported defects
reporter=6
# the resolution will need to be set manually
resolution=""
db = MySQLdb.connect(db='bugs',user='root',host='localhost')
cursor = db.cursor()
cursor.execute( "INSERT INTO bugs SET " \
"bug_id=%s," \
"bug_severity='normal'," \
"bug_status=%s," \
"creation_ts=%s," \
"short_desc=%s," \
"product=%s," \
"rep_platform='All'," \
"assigned_to=%s,"
"reporter=%s," \
"version=%s," \
"component=%s," \
"resolution=%s",
[ current['number'],
bug_status,
time.strftime("%Y-%m-%d %H:%M:%S", current['date-reported'][:9]),
current['short-description'],
product,
reporter,
reporter,
version,
component,
resolution] )
# This is the initial long description associated with the bug report
cursor.execute( "INSERT INTO longdescs VALUES (%s,%s,%s,%s)",
[ current['number'],
reporter,
time.strftime("%Y-%m-%d %H:%M:%S", current['date-reported'][:9]),
current['description'] ] )
# Add whatever notes are associated with this defect
for n in current['notes']:
cursor.execute( "INSERT INTO longdescs VALUES (%s,%s,%s,%s)",
[current['number'],
reporter,
time.strftime("%Y-%m-%d %H:%M:%S", n['timestamp'][:9]),
n['text']])
# add attachments associated with this defect
for a in current['attachments']:
cursor.execute( "INSERT INTO attachments SET " \
"bug_id=%s, creation_ts=%s, description='', mimetype=%s," \
"filename=%s, thedata=%s, submitter_id=%s",
[ current['number'],
time.strftime("%Y-%m-%d %H:%M:%S", current['date-reported'][:9]),
a[1], a[0], a[2], reporter ])
cursor.close()
db.close()
def usage():
print """Usage: jb2bz.py [OPTIONS] Product
Where OPTIONS are one or more of the following:
-h This help information.
-s STATUS One of UNCONFIRMED, NEW, ASSIGNED, REOPENED, RESOLVED, VERIFIED, CLOSED
(default is NEW)
-c COMPONENT The component to attach to each bug as it is important. This should be
valid component for the Product.
-v VERSION Version to assign to these defects.
Product is the Product to assign these defects to.
All of the JitterBugs in the current directory are imported, including replies, notes,
attachments, and similar noise.
"""
sys.exit(1)
def main():
global bug_status, component, version, product
opts, args = getopt.getopt(sys.argv[1:], "hs:c:v:")
for o,a in opts:
if o == "-s":
if a in ('UNCONFIRMED','NEW','ASSIGNED','REOPENED','RESOLVED','VERIFIED','CLOSED'):
bug_status = a
elif o == '-c':
component = a
elif o == '-v':
version = a
elif o == '-h':
usage()
if len(args) != 1:
sys.stderr.write("Must specify the Product.\n")
sys.exit(1)
product = args[0]
for bug in filter(lambda x: re.match(r"\d+$", x), glob.glob("*")):
process_jitterbug(bug)
if __name__ == "__main__":
main()

View File

@@ -1,102 +0,0 @@
#!/usr/bonsaitools/bin/perl -w
#
# 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 the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 2000 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Dan Mosedale <dmose@mozilla.org>
#
# mysqld-watcher.pl - a script that watches the running instance of
# mysqld and kills off any long-running SELECTs against the shadow_db
#
use diagnostics;
use strict;
require "globals.pl";
# some configurables:
# length of time before a thread is eligible to be killed, in seconds
#
my $long_query_time = 600;
#
# the From header for any messages sent out
#
my $mail_from = "root\@lounge.mozilla.org";
#
# mail transfer agent. this should probably really be converted to a Param().
#
my $mta_program = "/usr/lib/sendmail -t -ODeliveryMode=deferred";
# and STDIN is where we get the info about running threads
#
close(STDIN);
open(STDIN, "/usr/bonsaitools/bin/mysqladmin processlist |");
# iterate through the running threads
#
my @LONGEST = (0,0,0,0,0,0,0,0,0);
while ( <STDIN> ) {
my @F = split(/\|/);
# if this line is not the correct number of fields, or if the thread-id
# field contains Id, skip this line. both these cases indicate that this
# line contains pretty-printing gunk and not thread info.
#
next if ( $#F != 9 || $F[1] =~ /Id/);
if ( $F[4] =~ /shadow_bugs/ # shadowbugs database in use
&& $F[5] =~ /Query/ # this is actually a query
&& $F[6] > $long_query_time # this query has taken too long
&& $F[8] =~ /(select|SELECT)/ # only kill a select
&& $F[6] > $LONGEST[6] ) { # the longest running query seen
@LONGEST = @F;
}
}
# send an email message
#
# should perhaps be moved to somewhere more global for use in bugzilla as a
# whole; should also do more error-checking
#
sub sendEmail($$$$) {
($#_ == 3) || die("sendEmail: invalid number of arguments");
my ($from, $to, $subject, $body) = @_;
open(MTA, "|$mta_program");
print MTA "From: $from\n";
print MTA "To: $to\n";
print MTA "Subject: $subject\n";
print MTA "\n";
print MTA $body;
print MTA "\n";
close(MTA);
}
# if we found anything, kill the database thread and send mail about it
#
if ($LONGEST[6] != 0) {
system ("/usr/bonsaitools/bin/mysqladmin", "kill", $LONGEST[1]);
# fire off an email telling the maintainer that we had to kill a thread
#
sendEmail($mail_from, Param("maintainer"),
"long running MySQL thread killed",
join(" ", @LONGEST) . "\n");
}

View File

@@ -1,78 +0,0 @@
#!/bin/sh
# -*- Mode: ksh -*-
##############################################################################
# $Id: yp_nomail.sh,v 1.1 2000-09-12 23:50:31 cyeh%bluemartini.com Exp $
# yp_nomail
#
# Our mail admins got annoyed when bugzilla kept sending email
# to people who'd had bugzilla entries and left the company. They
# were no longer in the list of valid email users so it'd bounce.
# Maintaining the 'data/nomail' file was a pain. Luckily, our UNIX
# admins list all the users that ever were, but the people who've left
# have a distinct marker in their password file. For example:
#
# fired:*LK*:2053:1010:You're Fired Dude:/home/loser:/bin/false
#
# This script takes advantage of the "*LK*" convention seen via
# ypcat passwd and dumps those people into the nomail file. Any
# manual additions are kept in a "nomail.(domainname)" file and
# appended to the list of yp lockouts every night via Cron
#
# 58 23 * * * /export/bugzilla/contrib/yp_nomail.sh > /dev/null 2>&1
#
# Tak ( Mark Takacs ) 08/2000
#
# XXX: Maybe should crosscheck w/bugzilla users?
##############################################################################
####
# Configure this section to suite yer installation
####
DOMAIN=`domainname`
MOZILLA_HOME="/export/mozilla"
BUGZILLA_HOME="${MOZILLA_HOME}/bugzilla"
NOMAIL_DIR="${BUGZILLA_HOME}/data"
NOMAIL="${NOMAIL_DIR}/nomail"
NOMAIL_ETIME="${NOMAIL}.${DOMAIN}"
NOMAIL_YP="${NOMAIL}.yp"
FIRED_FLAG="\*LK\*"
YPCAT="/usr/bin/ypcat"
GREP="/usr/bin/grep"
SORT="/usr/bin/sort"
########################## no more config needed #################
# This dir comes w/Bugzilla. WAY too paranoid
if [ ! -d ${NOMAIL_DIR} ] ; then
echo "Creating $date_dir"
mkdir -p ${NOMAIL_DIR}
fi
#
# Do some (more) paranoid checking
#
touch ${NOMAIL}
if [ ! -w ${NOMAIL} ] ; then
echo "Can't write nomail file: ${NOMAIL} -- exiting"
exit
fi
if [ ! -r ${NOMAIL_ETIME} ] ; then
echo "Can't access custom nomail file: ${NOMAIL_ETIME} -- skipping"
NOMAIL_ETIME=""
fi
#
# add all the people with '*LK*' password to the nomail list
# XXX: maybe I should customize the *LK* string. Doh.
#
LOCKOUT=`$YPCAT passwd | $GREP "${FIRED_FLAG}" | cut -d: -f1 | sort > ${NOMAIL_YP}`
`cat ${NOMAIL_YP} ${NOMAIL_ETIME} > ${NOMAIL}`
exit
# end

View File

@@ -1,88 +0,0 @@
#!/usr/bonsaitools/bin/perl -wT
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# 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 the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Terry Weissman <terry@mozilla.org>
# David Gardiner <david.gardiner@unisa.edu.au>
# Joe Robins <jmrobins@tgix.com>
# Christopher Aillon <christopher@aillon.com>
# Gervase Markham <gerv@gerv.net>
use diagnostics;
use strict;
use lib qw(.);
require "CGI.pl";
require "globals.pl";
# Shut up misguided -w warnings about "used only once":
use vars qw(
%FORM
$template
$vars
);
ConnectToDatabase();
# If we're using LDAP for login, then we can't create a new account here.
if(Param('useLDAP')) {
DisplayError("This site is using LDAP for authentication. Please contact
an LDAP administrator to get a new account created.",
"Can't create LDAP accounts");
PutFooter();
exit;
}
# Clear out the login cookies. Make people log in again if they create an
# account; otherwise, they'll probably get confused.
my $cookiepath = Param("cookiepath");
print "Set-Cookie: Bugzilla_login= ; path=$cookiepath; expires=Sun, 30-Jun-80 00:00:00 GMT
Set-Cookie: Bugzilla_logincookie= ; path=$cookiepath; expires=Sun, 30-Jun-80 00:00:00 GMT\n";
print "Content-Type: text/html\n\n";
my $login = $::FORM{'login'};
my $realname = trim($::FORM{'realname'});
if (defined($login)) {
# We've been asked to create an account.
CheckEmailSyntax($login);
trick_taint($login);
$vars->{'login'} = $login;
if (!ValidateNewUser($login)) {
# Account already exists
$template->process("account/exists.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
exit;
}
# Create account
my $password = InsertNewUser($login, $realname);
MailPassword($login, $password);
$template->process("account/created.html.tmpl", $vars)
|| ThrowTemplateError($template->error());
exit;
}
# Show the standard "would you like to create an account?" form.
$template->process("account/create.html.tmpl", $vars)
|| ThrowTemplateError($template->error());

Some files were not shown because too many files have changed in this diff Show More