mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-05-13 08:57:27 +00:00
410 lines
12 KiB
C++
410 lines
12 KiB
C++
/* -*- 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.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
|
|
|
|
#include "nsPolygonFrame.h"
|
|
|
|
#include "nsIDOMElement.h"
|
|
#include "nsIContent.h"
|
|
#include "prtypes.h"
|
|
#include "nsIAtom.h"
|
|
#include "nsHTMLAtoms.h"
|
|
#include "nsIPresContext.h"
|
|
#include "nsIStyleContext.h"
|
|
#include "nsCSSRendering.h"
|
|
#include "nsINameSpaceManager.h"
|
|
#include "nsColor.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsPoint.h"
|
|
#include "nsSVGAtoms.h"
|
|
#include "nsIDeviceContext.h"
|
|
#include "nsGUIEvent.h"
|
|
|
|
#include "nsIReflowCommand.h"
|
|
extern nsresult
|
|
NS_NewHTMLReflowCommand(nsIReflowCommand** aInstancePtrResult,
|
|
nsIFrame* aTargetFrame,
|
|
nsIReflowCommand::ReflowType aReflowType,
|
|
nsIFrame* aChildFrame = nsnull,
|
|
nsIAtom* aAttribute = nsnull);
|
|
//#include "nsPolygonCID.h"
|
|
//
|
|
// NS_NewPolygonFrame
|
|
//
|
|
// Wrapper for creating a new color picker
|
|
//
|
|
nsresult
|
|
NS_NewPolygonFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
|
|
{
|
|
NS_PRECONDITION(aNewFrame, "null OUT ptr");
|
|
if (nsnull == aNewFrame) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
nsPolygonFrame* it = new (aPresShell) nsPolygonFrame;
|
|
if ( !it )
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
*aNewFrame = it;
|
|
return NS_OK;
|
|
}
|
|
|
|
// static NS_DEFINE_IID(kDefPolygonCID, NS_DEFCOLORPICKER_CID);
|
|
|
|
//
|
|
// nsPolygonFrame cntr
|
|
//
|
|
nsPolygonFrame::nsPolygonFrame() :
|
|
mPnts(nsnull),
|
|
mNumPnts(0),
|
|
mX(0),
|
|
mY(0),
|
|
mPresContext(nsnull)
|
|
{
|
|
|
|
}
|
|
|
|
nsPolygonFrame::~nsPolygonFrame()
|
|
{
|
|
if (mPnts) {
|
|
delete [] mPnts;
|
|
}
|
|
NS_IF_RELEASE(mPresContext);
|
|
}
|
|
|
|
|
|
NS_IMETHODIMP
|
|
nsPolygonFrame::Init(nsIPresContext* aPresContext,
|
|
nsIContent* aContent,
|
|
nsIFrame* aParent,
|
|
nsIStyleContext* aContext,
|
|
nsIFrame* aPrevInFlow)
|
|
{
|
|
mPresContext = aPresContext;
|
|
NS_ADDREF(mPresContext);
|
|
|
|
nsresult rv = nsLeafFrame::Init(aPresContext, aContent, aParent, aContext,
|
|
aPrevInFlow);
|
|
|
|
|
|
nsAutoString type;
|
|
mContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::type, type);
|
|
|
|
if (type.EqualsIgnoreCase(NS_ConvertASCIItoUCS2("swatch")) || type.IsEmpty())
|
|
{
|
|
//mPolygon = new nsStdPolygon();
|
|
//mPolygon->Init(mContent);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
//--------------------------------------------------------------
|
|
// Frames are not refcounted, no need to AddRef
|
|
NS_IMETHODIMP
|
|
nsPolygonFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
|
{
|
|
NS_PRECONDITION(0 != aInstancePtr, "null ptr");
|
|
if (NULL == aInstancePtr) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
|
|
if (aIID.Equals(NS_GET_IID(nsISVGFrame))) {
|
|
*aInstancePtr = (void*) ((nsISVGFrame*) this);
|
|
return NS_OK;
|
|
}
|
|
return nsLeafFrame::QueryInterface(aIID, aInstancePtr);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
//-- Main Reflow for the Polygon
|
|
//-------------------------------------------------------------------
|
|
NS_IMETHODIMP
|
|
nsPolygonFrame::Reflow(nsIPresContext* aPresContext,
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
|
const nsHTMLReflowState& aReflowState,
|
|
nsReflowStatus& aStatus)
|
|
{
|
|
aStatus = NS_FRAME_COMPLETE;
|
|
|
|
nsCOMPtr<nsIDeviceContext> dx;
|
|
aPresContext->GetDeviceContext(getter_AddRefs(dx));
|
|
float p2t = 1.0;
|
|
float scale = 1.0;
|
|
if (dx) {
|
|
aPresContext->GetPixelsToTwips(&p2t);
|
|
dx->GetCanonicalPixelScale(scale);
|
|
}
|
|
|
|
nsAutoString coordStr;
|
|
nsresult res = mContent->GetAttr(kNameSpaceID_None, nsSVGAtoms::x, coordStr);
|
|
if (NS_SUCCEEDED(res)) {
|
|
char * s = coordStr.ToNewCString();
|
|
mX = NSIntPixelsToTwips(atoi(s), p2t*scale);
|
|
delete [] s;
|
|
}
|
|
|
|
res = mContent->GetAttr(kNameSpaceID_None, nsSVGAtoms::y, coordStr);
|
|
if (NS_SUCCEEDED(res)) {
|
|
char * s = coordStr.ToNewCString();
|
|
mY = NSIntPixelsToTwips(atoi(s), p2t*scale);
|
|
delete [] s;
|
|
}
|
|
|
|
if (mPoints.Count() == 0) {
|
|
GetPoints();
|
|
// Convert points from Pixels to twips
|
|
// and these points are relative to the X & Y
|
|
// then find max width and height
|
|
nscoord maxWidth = 0;
|
|
nscoord maxHeight = 0;
|
|
for (PRInt32 i=0;i<mNumPnts;i++) {
|
|
mPnts[i].x = NSIntPixelsToTwips(mPnts[i].x, p2t*scale);
|
|
mPnts[i].y = NSIntPixelsToTwips(mPnts[i].y, p2t*scale);
|
|
maxWidth = PR_MAX(maxWidth, mPnts[i].x);
|
|
maxHeight = PR_MAX(maxHeight, mPnts[i].y);
|
|
}
|
|
aDesiredSize.width = maxWidth + nscoord(p2t*scale);
|
|
aDesiredSize.height = maxHeight + nscoord(p2t*scale);
|
|
} else {
|
|
aDesiredSize.width = mRect.width;
|
|
aDesiredSize.height = mRect.height;
|
|
}
|
|
|
|
aDesiredSize.ascent = aDesiredSize.height;
|
|
aDesiredSize.descent = 0;
|
|
|
|
if (nsnull != aDesiredSize.maxElementSize) {
|
|
aDesiredSize.maxElementSize->width = aDesiredSize.width;
|
|
aDesiredSize.maxElementSize->height = aDesiredSize.height;
|
|
}
|
|
//nsRect rect(0, 0, aDesiredSize.width, aDesiredSize.height);
|
|
//Invalidate(aPresContext, rect, PR_TRUE);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsPolygonFrame::HandleEvent(nsIPresContext* aPresContext,
|
|
nsGUIEvent* aEvent,
|
|
nsEventStatus* aEventStatus)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aEventStatus);
|
|
*aEventStatus = nsEventStatus_eConsumeDoDefault;
|
|
if (aEvent->message == NS_MOUSE_LEFT_BUTTON_DOWN)
|
|
HandleMouseDownEvent(aPresContext, aEvent, aEventStatus);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
nsPolygonFrame::HandleMouseDownEvent(nsIPresContext* aPresContext,
|
|
nsGUIEvent* aEvent,
|
|
nsEventStatus* aEventStatus)
|
|
{
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
// XXX - Quick and Dirty impl to get somethinf working
|
|
// this should be rewritten
|
|
NS_METHOD
|
|
nsPolygonFrame::GetPoints()
|
|
{
|
|
if (mPnts != nsnull) {
|
|
delete [] mPnts;
|
|
mNumPnts = 0;
|
|
mPoints.Clear();
|
|
}
|
|
|
|
nsAutoString pointsStr;
|
|
nsresult res = mContent->GetAttr(kNameSpaceID_None, nsSVGAtoms::points, pointsStr);
|
|
|
|
char * ps = pointsStr.ToNewCString();
|
|
char seps[] = " ";
|
|
char *token = strtok(ps, seps);
|
|
PRInt32 cnt = 0;
|
|
nsPoint * pnt = nsnull;
|
|
while (token != NULL) {
|
|
if (cnt % 2 == 0) {
|
|
pnt = new nsPoint;
|
|
mPoints.AppendElement((void*)pnt);
|
|
pnt->x = atoi(token);
|
|
} else {
|
|
pnt->y = atoi(token);
|
|
}
|
|
token = strtok( NULL, seps );
|
|
cnt++;
|
|
}
|
|
|
|
delete [] ps;
|
|
|
|
mNumPnts = mPoints.Count()+1;
|
|
mPnts = new nsPoint[mNumPnts];
|
|
for (cnt=0;cnt<mNumPnts-1;cnt++) {
|
|
pnt = NS_REINTERPRET_CAST(nsPoint*, mPoints.ElementAt(cnt));
|
|
mPnts[cnt] = *pnt;
|
|
delete pnt;
|
|
}
|
|
mPnts[mNumPnts-1] = mPnts[0];
|
|
|
|
//printf("0x%X Points are:\n", this);
|
|
//for (PRInt32 i=0;i<mNumPnts;i++) {
|
|
// printf("%d -> [%d,%d]\n", i, mPnts[i].x, mPnts[i].y);
|
|
//}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsPolygonFrame::SetProperty(nsIPresContext* aPresContext,
|
|
nsIAtom* aName,
|
|
const nsString& aValue)
|
|
{
|
|
if (aName == nsSVGAtoms::points) {
|
|
} else if (aName == nsSVGAtoms::x) {
|
|
} else if (aName == nsSVGAtoms::y) {
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsPolygonFrame::AttributeChanged(nsIPresContext* aPresContext,
|
|
nsIContent* aChild,
|
|
PRInt32 aNameSpaceID,
|
|
nsIAtom* aAttribute,
|
|
PRInt32 aModType,
|
|
PRInt32 aHint)
|
|
{
|
|
if (aAttribute == nsSVGAtoms::points) {
|
|
//GetPoints();
|
|
mPoints.Clear();
|
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
aPresContext->GetShell(getter_AddRefs(shell));
|
|
|
|
nsIReflowCommand* reflowCmd;
|
|
nsresult rv = NS_NewHTMLReflowCommand(&reflowCmd, this,
|
|
nsIReflowCommand::ContentChanged);
|
|
if (NS_SUCCEEDED(rv)) {
|
|
shell->AppendReflowCommand(reflowCmd);
|
|
NS_RELEASE(reflowCmd);
|
|
rv = shell->FlushPendingNotifications(PR_FALSE);
|
|
}
|
|
} else if (aAttribute == nsSVGAtoms::x) {
|
|
} else if (aAttribute == nsSVGAtoms::y) {
|
|
}
|
|
return nsLeafFrame::AttributeChanged(aPresContext, aChild, aNameSpaceID, aAttribute, aModType, aHint);
|
|
}
|
|
|
|
NS_METHOD nsPolygonFrame::RenderPoints(nsIRenderingContext& aRenderingContext,
|
|
const nsPoint aPoints[], PRInt32 aNumPoints)
|
|
{
|
|
//nsAutoString fillStr;
|
|
//nsresult res = mContent->GetAttr(kNameSpaceID_None, nsSVGAtoms::fill, fillStr);
|
|
//if (NS_SUCCEEDED(res)) {
|
|
aRenderingContext.FillPolygon(aPoints, aNumPoints);
|
|
//} else {
|
|
// aRenderingContext.DrawPolygon(aPoints, aNumPoints);
|
|
//}
|
|
return NS_OK;
|
|
}
|
|
|
|
//
|
|
// Paint
|
|
//
|
|
//
|
|
NS_METHOD
|
|
nsPolygonFrame::Paint(nsIPresContext* aPresContext,
|
|
nsIRenderingContext& aRenderingContext,
|
|
const nsRect& aDirtyRect,
|
|
nsFramePaintLayer aWhichLayer)
|
|
{
|
|
|
|
// if we aren't visible then we are done.
|
|
const nsStyleVisibility* visib = NS_STATIC_CAST(const nsStyleVisibility*,
|
|
mStyleContext->GetStyleData(eStyleStruct_Visibility));
|
|
if (!visib->IsVisibleOrCollapsed())
|
|
return NS_OK;
|
|
|
|
if (aWhichLayer == NS_FRAME_PAINT_LAYER_BACKGROUND) {
|
|
// if we are visible then tell our superclass to paint
|
|
nsLeafFrame::Paint(aPresContext, aRenderingContext, aDirtyRect,
|
|
aWhichLayer);
|
|
}
|
|
|
|
if (aWhichLayer == NS_FRAME_PAINT_LAYER_FOREGROUND) {
|
|
|
|
// get our border
|
|
const nsStyleBorder* borderStyle = (const nsStyleBorder*)mStyleContext->GetStyleData(eStyleStruct_Border);
|
|
nsMargin border(0,0,0,0);
|
|
borderStyle->CalcBorderFor(this, border);
|
|
|
|
|
|
// XXX - Color needs to comes from new style property fill
|
|
// and not mColor
|
|
const nsStyleColor* colorStyle = (const nsStyleColor*)mStyleContext->GetStyleData(eStyleStruct_Color);
|
|
nscolor color = colorStyle->mColor;
|
|
|
|
|
|
aRenderingContext.PushState();
|
|
|
|
// set the clip region
|
|
nsRect rect;
|
|
|
|
PRBool clipState;
|
|
GetRect(rect);
|
|
|
|
// Clip so we don't render outside the inner rect
|
|
rect.x = 0;
|
|
rect.y = 0;
|
|
aRenderingContext.SetClipRect(rect, nsClipCombine_kReplace, clipState);
|
|
aRenderingContext.SetColor(color);
|
|
|
|
///////////////////////////////////////////
|
|
// XXX - This is all just a quick hack
|
|
// needs to be rewritten
|
|
nsPoint points[256];
|
|
for (PRInt32 i=0;i<mNumPnts;i++) {
|
|
points[i] = mPnts[i];
|
|
}
|
|
// XXX - down to here
|
|
|
|
RenderPoints(aRenderingContext, points, mNumPnts);
|
|
|
|
aRenderingContext.PopState(clipState);
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
//
|
|
// GetDesiredSize
|
|
//
|
|
// For now, be as big as CSS wants us to be, or some small default size.
|
|
//
|
|
void
|
|
nsPolygonFrame::GetDesiredSize(nsIPresContext* aPresContext,
|
|
const nsHTMLReflowState& aReflowState,
|
|
nsHTMLReflowMetrics& aDesiredSize)
|
|
{
|
|
NS_ASSERTION(0, "Who called this? and Why?");
|
|
} // GetDesiredSize
|