michael@0: michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #include "SkDrawPaint.h" michael@0: #include "SkAnimateMaker.h" michael@0: #include "SkDrawColor.h" michael@0: #include "SkDrawShader.h" michael@0: #include "SkMaskFilter.h" michael@0: #include "SkPaintParts.h" michael@0: #include "SkPathEffect.h" michael@0: michael@0: enum SkPaint_Functions { michael@0: SK_FUNCTION(measureText) michael@0: }; michael@0: michael@0: enum SkPaint_Properties { michael@0: SK_PROPERTY(ascent), michael@0: SK_PROPERTY(descent) michael@0: }; michael@0: michael@0: // !!! in the future, this could be compiled by build-condensed-info into an array of parameters michael@0: // with a lookup table to find the first parameter -- for now, it is iteratively searched through michael@0: const SkFunctionParamType SkDrawPaint::fFunctionParameters[] = { michael@0: (SkFunctionParamType) SkType_String, michael@0: (SkFunctionParamType) 0 // terminator for parameter list (there may be multiple parameter lists) michael@0: }; michael@0: michael@0: michael@0: #if SK_USE_CONDENSED_INFO == 0 michael@0: michael@0: const SkMemberInfo SkDrawPaint::fInfo[] = { michael@0: SK_MEMBER(antiAlias, Boolean), michael@0: SK_MEMBER_PROPERTY(ascent, Float), michael@0: SK_MEMBER(color, Color), michael@0: SK_MEMBER_PROPERTY(descent, Float), michael@0: SK_MEMBER(fakeBold, Boolean), michael@0: SK_MEMBER(filterBitmap, Boolean), michael@0: SK_MEMBER(linearText, Boolean), michael@0: SK_MEMBER(maskFilter, MaskFilter), michael@0: SK_MEMBER_FUNCTION(measureText, Float), michael@0: SK_MEMBER(pathEffect, PathEffect), michael@0: SK_MEMBER(shader, Shader), michael@0: SK_MEMBER(strikeThru, Boolean), michael@0: SK_MEMBER(stroke, Boolean), michael@0: SK_MEMBER(strokeCap, Cap), michael@0: SK_MEMBER(strokeJoin, Join), michael@0: SK_MEMBER(strokeMiter, Float), michael@0: SK_MEMBER(strokeWidth, Float), michael@0: SK_MEMBER(style, Style), michael@0: SK_MEMBER(textAlign, Align), michael@0: SK_MEMBER(textScaleX, Float), michael@0: SK_MEMBER(textSize, Float), michael@0: SK_MEMBER(textSkewX, Float), michael@0: SK_MEMBER(typeface, Typeface), michael@0: SK_MEMBER(underline, Boolean), michael@0: SK_MEMBER(xfermode, Xfermode) michael@0: }; michael@0: michael@0: #endif michael@0: michael@0: DEFINE_GET_MEMBER(SkDrawPaint); michael@0: michael@0: SkDrawPaint::SkDrawPaint() : antiAlias(-1), color(NULL), fakeBold(-1), filterBitmap(-1), michael@0: linearText(-1), maskFilter((SkDrawMaskFilter*) -1), pathEffect((SkDrawPathEffect*) -1), michael@0: shader((SkDrawShader*) -1), strikeThru(-1), stroke(-1), michael@0: strokeCap((SkPaint::Cap) -1), strokeJoin((SkPaint::Join) -1), strokeMiter(SK_ScalarNaN), michael@0: strokeWidth(SK_ScalarNaN), style((SkPaint::Style) -1), michael@0: textAlign((SkPaint::Align) -1), textScaleX(SK_ScalarNaN), textSize(SK_ScalarNaN), michael@0: textSkewX(SK_ScalarNaN), typeface((SkDrawTypeface*) -1), michael@0: underline(-1), xfermode((SkXfermode::Mode) -1), fOwnsColor(false), fOwnsMaskFilter(false), michael@0: fOwnsPathEffect(false), fOwnsShader(false), fOwnsTypeface(false) { michael@0: } michael@0: michael@0: SkDrawPaint::~SkDrawPaint() { michael@0: if (fOwnsColor) michael@0: delete color; michael@0: if (fOwnsMaskFilter) michael@0: delete maskFilter; michael@0: if (fOwnsPathEffect) michael@0: delete pathEffect; michael@0: if (fOwnsShader) michael@0: delete shader; michael@0: if (fOwnsTypeface) michael@0: delete typeface; michael@0: } michael@0: michael@0: bool SkDrawPaint::add(SkAnimateMaker* maker, SkDisplayable* child) { michael@0: SkASSERT(child && child->isPaintPart()); michael@0: SkPaintPart* part = (SkPaintPart*) child; michael@0: if (part->add() && maker) michael@0: maker->setErrorCode(SkDisplayXMLParserError::kErrorAddingToPaint); michael@0: return true; michael@0: } michael@0: michael@0: SkDisplayable* SkDrawPaint::deepCopy(SkAnimateMaker* maker) { michael@0: SkDrawColor* tempColor = color; michael@0: color = NULL; michael@0: SkDrawPaint* copy = (SkDrawPaint*) INHERITED::deepCopy(maker); michael@0: color = tempColor; michael@0: tempColor = (SkDrawColor*) color->deepCopy(maker); michael@0: tempColor->setParent(copy); michael@0: tempColor->add(); michael@0: copy->fOwnsColor = true; michael@0: return copy; michael@0: } michael@0: michael@0: bool SkDrawPaint::draw(SkAnimateMaker& maker) { michael@0: SkPaint* paint = maker.fPaint; michael@0: setupPaint(paint); michael@0: return false; michael@0: } michael@0: michael@0: #ifdef SK_DUMP_ENABLED michael@0: void SkDrawPaint::dump(SkAnimateMaker* maker) { michael@0: dumpBase(maker); michael@0: dumpAttrs(maker); michael@0: bool closedYet = false; michael@0: SkDisplayList::fIndent +=4; michael@0: //should i say if (maskFilter && ...? michael@0: if (maskFilter != (SkDrawMaskFilter*)-1) { michael@0: SkDebugf(">\n"); michael@0: maskFilter->dump(maker); michael@0: closedYet = true; michael@0: } michael@0: if (pathEffect != (SkDrawPathEffect*) -1) { michael@0: if (closedYet == false) { michael@0: SkDebugf(">\n"); michael@0: closedYet = true; michael@0: } michael@0: pathEffect->dump(maker); michael@0: } michael@0: if (fOwnsTypeface) { michael@0: if (closedYet == false) { michael@0: SkDebugf(">\n"); michael@0: closedYet = true; michael@0: } michael@0: typeface->dump(maker); michael@0: } michael@0: SkDisplayList::fIndent -= 4; michael@0: dumpChildren(maker, closedYet); michael@0: } michael@0: #endif michael@0: michael@0: void SkDrawPaint::executeFunction(SkDisplayable* target, int index, michael@0: SkTDArray& parameters, SkDisplayTypes type, michael@0: SkScriptValue* scriptValue) { michael@0: if (scriptValue == NULL) michael@0: return; michael@0: SkASSERT(target == this); michael@0: switch (index) { michael@0: case SK_FUNCTION(measureText): { michael@0: SkASSERT(parameters.count() == 1); michael@0: SkASSERT(type == SkType_Float); michael@0: SkPaint paint; michael@0: setupPaint(&paint); michael@0: scriptValue->fType = SkType_Float; michael@0: SkASSERT(parameters[0].fType == SkType_String); michael@0: scriptValue->fOperand.fScalar = paint.measureText(parameters[0].fOperand.fString->c_str(), michael@0: parameters[0].fOperand.fString->size()); michael@0: // SkDebugf("measureText: %s = %g\n", parameters[0].fOperand.fString->c_str(), michael@0: // scriptValue->fOperand.fScalar / 65536.0f); michael@0: } break; michael@0: default: michael@0: SkASSERT(0); michael@0: } michael@0: } michael@0: michael@0: const SkFunctionParamType* SkDrawPaint::getFunctionsParameters() { michael@0: return fFunctionParameters; michael@0: } michael@0: michael@0: bool SkDrawPaint::getProperty(int index, SkScriptValue* value) const { michael@0: SkPaint::FontMetrics metrics; michael@0: SkPaint paint; michael@0: setupPaint(&paint); michael@0: paint.getFontMetrics(&metrics); michael@0: switch (index) { michael@0: case SK_PROPERTY(ascent): michael@0: value->fOperand.fScalar = metrics.fAscent; michael@0: break; michael@0: case SK_PROPERTY(descent): michael@0: value->fOperand.fScalar = metrics.fDescent; michael@0: break; michael@0: // should consider returning fLeading as well (or roll it into ascent/descent somehow michael@0: default: michael@0: SkASSERT(0); michael@0: return false; michael@0: } michael@0: value->fType = SkType_Float; michael@0: return true; michael@0: } michael@0: michael@0: bool SkDrawPaint::resolveIDs(SkAnimateMaker& maker, SkDisplayable* origDisp, SkApply* ) { michael@0: SkASSERT(origDisp->isPaint()); michael@0: SkDrawPaint* original = (SkDrawPaint*) origDisp; michael@0: if (fOwnsColor && maker.resolveID(color, original->color) == false) michael@0: return true; michael@0: if (fOwnsMaskFilter && maker.resolveID(maskFilter, original->maskFilter) == false) michael@0: return true; michael@0: if (fOwnsPathEffect && maker.resolveID(pathEffect, original->pathEffect) == false) michael@0: return true; michael@0: if (fOwnsShader && maker.resolveID(shader, original->shader) == false) michael@0: return true; michael@0: if (fOwnsTypeface && maker.resolveID(typeface, original->typeface) == false) michael@0: return true; michael@0: return false; // succeeded michael@0: } michael@0: michael@0: void SkDrawPaint::setupPaint(SkPaint* paint) const { michael@0: if (antiAlias != -1) michael@0: paint->setAntiAlias(SkToBool(antiAlias)); michael@0: if (color != NULL) michael@0: paint->setColor(color->getColor()); michael@0: if (fakeBold != -1) michael@0: paint->setFakeBoldText(SkToBool(fakeBold)); michael@0: if (filterBitmap != -1) michael@0: paint->setFilterLevel(filterBitmap ? SkPaint::kLow_FilterLevel : SkPaint::kNone_FilterLevel); michael@0: // stroke is legacy; style setting if present overrides stroke michael@0: if (stroke != -1) michael@0: paint->setStyle(SkToBool(stroke) ? SkPaint::kStroke_Style : SkPaint::kFill_Style); michael@0: if (style != -1) michael@0: paint->setStyle((SkPaint::Style) style); michael@0: if (linearText != -1) michael@0: paint->setLinearText(SkToBool(linearText)); michael@0: if (maskFilter == NULL) michael@0: paint->setMaskFilter(NULL); michael@0: else if (maskFilter != (SkDrawMaskFilter*) -1) michael@0: SkSafeUnref(paint->setMaskFilter(maskFilter->getMaskFilter())); michael@0: if (pathEffect == NULL) michael@0: paint->setPathEffect(NULL); michael@0: else if (pathEffect != (SkDrawPathEffect*) -1) michael@0: SkSafeUnref(paint->setPathEffect(pathEffect->getPathEffect())); michael@0: if (shader == NULL) michael@0: paint->setShader(NULL); michael@0: else if (shader != (SkDrawShader*) -1) michael@0: SkSafeUnref(paint->setShader(shader->getShader())); michael@0: if (strikeThru != -1) michael@0: paint->setStrikeThruText(SkToBool(strikeThru)); michael@0: if (strokeCap != -1) michael@0: paint->setStrokeCap((SkPaint::Cap) strokeCap); michael@0: if (strokeJoin != -1) michael@0: paint->setStrokeJoin((SkPaint::Join) strokeJoin); michael@0: if (SkScalarIsNaN(strokeMiter) == false) michael@0: paint->setStrokeMiter(strokeMiter); michael@0: if (SkScalarIsNaN(strokeWidth) == false) michael@0: paint->setStrokeWidth(strokeWidth); michael@0: if (textAlign != -1) michael@0: paint->setTextAlign((SkPaint::Align) textAlign); michael@0: if (SkScalarIsNaN(textScaleX) == false) michael@0: paint->setTextScaleX(textScaleX); michael@0: if (SkScalarIsNaN(textSize) == false) michael@0: paint->setTextSize(textSize); michael@0: if (SkScalarIsNaN(textSkewX) == false) michael@0: paint->setTextSkewX(textSkewX); michael@0: if (typeface == NULL) michael@0: paint->setTypeface(NULL); michael@0: else if (typeface != (SkDrawTypeface*) -1) michael@0: SkSafeUnref(paint->setTypeface(typeface->getTypeface())); michael@0: if (underline != -1) michael@0: paint->setUnderlineText(SkToBool(underline)); michael@0: if (xfermode != -1) michael@0: paint->setXfermodeMode((SkXfermode::Mode) xfermode); michael@0: }