static void drawGlyphsShadow(GraphicsContext* graphicsContext, const FloatPoint& point, const SimpleFontData* font, GlyphBufferGlyph* glyphs, int numGlyphs)
{
    ShadowBlur& shadow = graphicsContext->platformContext()->shadowBlur();

    if (!(graphicsContext->textDrawingMode() & TextModeFill) || shadow.type() == ShadowBlur::NoShadow)
        return;

    if (!graphicsContext->mustUseShadowBlur()) {
        // Optimize non-blurry shadows, by just drawing text without the ShadowBlur.
        cairo_t* context = graphicsContext->platformContext()->cr();
        cairo_save(context);

        FloatSize shadowOffset(graphicsContext->state().shadowOffset);
        cairo_translate(context, shadowOffset.width(), shadowOffset.height());
        setSourceRGBAFromColor(context, graphicsContext->state().shadowColor);
        drawGlyphsToContext(context, font, glyphs, numGlyphs);

        cairo_restore(context);
        return;
    }

    cairo_text_extents_t extents;
    cairo_scaled_font_glyph_extents(font->platformData().scaledFont(), glyphs, numGlyphs, &extents);
    FloatRect fontExtentsRect(point.x() + extents.x_bearing, point.y() + extents.y_bearing, extents.width, extents.height);

    if (GraphicsContext* shadowContext = shadow.beginShadowLayer(graphicsContext, fontExtentsRect)) {
        drawGlyphsToContext(shadowContext->platformContext()->cr(), font, glyphs, numGlyphs);
        shadow.endShadowLayer(graphicsContext);
    }
}
Пример #2
0
void TextAttachment::SetShadow(bool enable, const Vector4& color, const Vector2& offset, const float size)
{
  AllocateTextParameters();

  if (enable != mTextParameters->mDropShadowEnabled ||
      color != mTextParameters->mDropShadowColor ||
      offset != mTextParameters->mDropShadow ||
      fabsf(size - mTextParameters->mDropShadowSize) > Math::MACHINE_EPSILON_1 )
  {
    mTextParameters->SetShadow( enable, color, offset, size );

    const float unitPointSize( 64.0f );
    const float unitsToPixels( mFont->GetUnitsToPixels());
    const float fontPointSize( mFont->GetPointSize() );

    float shadowSize( (size * 0.25f) / unitsToPixels );

    Vector2 shadowOffset( offset );
    Vector2 maxOffset( fontPointSize / 4.5f, fontPointSize / 4.5f );
    shadowOffset = Min( shadowOffset, maxOffset );
    shadowOffset = Max( shadowOffset, -maxOffset );
    shadowOffset *= unitPointSize / fontPointSize;
    SetDropShadowMessage( mStage->GetUpdateInterface(), *mSceneObject, enable, color, shadowOffset, shadowSize );
  }
}
Пример #3
0
void nsTextBoxFrame::PaintOneShadow(gfxContext*      aCtx,
                                    const nsRect&    aTextRect,
                                    nsCSSShadowItem* aShadowDetails,
                                    const nscolor&   aForegroundColor,
                                    const nsRect&    aDirtyRect) {
  nsPoint shadowOffset(aShadowDetails->mXOffset,
                       aShadowDetails->mYOffset);
  nscoord blurRadius = NS_MAX(aShadowDetails->mRadius, 0);

  nsRect shadowRect(aTextRect);
  shadowRect.MoveBy(shadowOffset);

  nsContextBoxBlur contextBoxBlur;
  gfxContext* shadowContext = contextBoxBlur.Init(shadowRect, 0, blurRadius,
                                                  PresContext()->AppUnitsPerDevPixel(),
                                                  aCtx, aDirtyRect, nsnull);

  if (!shadowContext)
    return;

  nscolor shadowColor;
  if (aShadowDetails->mHasColor)
    shadowColor = aShadowDetails->mColor;
  else
    shadowColor = aForegroundColor;

  // Conjure an nsIRenderingContext from a gfxContext for DrawText
  nsCOMPtr<nsIRenderingContext> renderingContext = nsnull;
  nsIDeviceContext* devCtx = PresContext()->DeviceContext();
  devCtx->CreateRenderingContextInstance(*getter_AddRefs(renderingContext));
  if (!renderingContext)
    return;
  renderingContext->Init(devCtx, shadowContext);

  aCtx->Save();
  aCtx->NewPath();
  aCtx->SetColor(gfxRGBA(shadowColor));

  // Draw the text onto our alpha-only surface to capture the alpha values.
  // Remember that the box blur context has a device offset on it, so we don't need to
  // translate any coordinates to fit on the surface.
  DrawText(*renderingContext, shadowRect, &shadowColor);
  contextBoxBlur.DoPaint();
  aCtx->Restore();
}
Пример #4
0
static void paintTextWithShadows(GraphicsContext* context, const TextRun& textRun, int startOffset, int endOffset, const IntPoint& textOrigin, int x, int y, int w, int h, ShadowData* shadow, bool stroked)
{
    do {
        IntSize extraOffset;

        if (shadow) {
            IntSize shadowOffset(shadow->x, shadow->y);
            int shadowBlur = shadow->blur;
            const Color& shadowColor = shadow->color;

            if (shadow->next || stroked) {
                IntRect shadowRect(x, y, w, h);
                shadowRect.inflate(shadowBlur);
                shadowRect.move(shadowOffset);
                context->save();
                context->clip(shadowRect);

                extraOffset = IntSize(0, 2 * h + max(0, shadowOffset.height()) + shadowBlur);
                shadowOffset -= extraOffset;
            }
            context->setShadow(shadowOffset, shadowBlur, shadowColor);
        }

        if (startOffset <= endOffset)
            context->drawText(textRun, textOrigin + extraOffset, startOffset, endOffset);
        else {
            if (endOffset > 0)
                context->drawText(textRun, textOrigin + extraOffset,  0, endOffset);
            if (startOffset < textRun.length())
                context->drawText(textRun, textOrigin + extraOffset, startOffset);
        }

        if (!shadow)
            break;

        if (shadow->next || stroked)
            context->restore();
        else
            context->clearShadow();

        shadow = shadow->next;
    } while (shadow || stroked);
}
Пример #5
0
ShadowApplier::ShadowApplier(GraphicsContext& context, const ShadowData* shadow, const FloatRect& textRect, bool lastShadowIterationShouldDrawText, bool opaque, FontOrientation orientation)
    : m_context(context)
    , m_shadow(shadow)
    , m_onlyDrawsShadow(!isLastShadowIteration() || !lastShadowIterationShouldDrawText)
    , m_avoidDrawingShadow(shadowIsCompletelyCoveredByText(opaque))
    , m_nothingToDraw(shadow && m_avoidDrawingShadow && m_onlyDrawsShadow)
    , m_didSaveContext(false)
{
    if (!shadow || m_nothingToDraw) {
        m_shadow = nullptr;
        return;
    }

    int shadowX = orientation == Horizontal ? shadow->x() : shadow->y();
    int shadowY = orientation == Horizontal ? shadow->y() : -shadow->x();
    FloatSize shadowOffset(shadowX, shadowY);
    int shadowRadius = shadow->radius();
    const Color& shadowColor = shadow->color();

    // When drawing shadows, we usually clip the context to the area the shadow will reside, and then
    // draw the text itself outside the clipped area (so only the shadow shows up). However, we can
    // often draw the *last* shadow and the text itself in a single call.
    if (m_onlyDrawsShadow) {
        FloatRect shadowRect(textRect);
        shadowRect.inflate(shadow->paintingExtent());
        shadowRect.move(shadowOffset);
        context.save();
        context.clip(shadowRect);

        m_didSaveContext = true;
        m_extraOffset = FloatSize(0, 2 * textRect.height() + std::max(0.0f, shadowOffset.height()) + shadowRadius);
        shadowOffset -= m_extraOffset;
    }

    if (!m_avoidDrawingShadow)
        context.setShadow(shadowOffset, shadowRadius, shadowColor, context.fillColorSpace());
}
Пример #6
0
void Text3D::UpdateTextMaterials(bool forceUpdate)
{
    batches_.Resize(uiBatches_.Size());
    geometries_.Resize(uiBatches_.Size());

    for (unsigned i = 0; i < batches_.Size(); ++i)
    {
        if (!geometries_[i])
        {
            Geometry* geometry = new Geometry(context_);
            geometry->SetVertexBuffer(0, vertexBuffer_, MASK_POSITION | MASK_COLOR | MASK_TEXCOORD1);
            batches_[i].geometry_ = geometries_[i] = geometry;
        }

        if (!batches_[i].material_ || forceUpdate)
        {
            // If material not defined, create a reasonable default from scratch
            if (!material_)
            {
                Material* material = new Material(context_);
                Technique* tech = new Technique(context_);
                Pass* pass = tech->CreatePass(PASS_ALPHA);
                pass->SetVertexShader("Text");
                pass->SetPixelShader("Text");

                if (GetFont()->IsSDFFont())
                {
                    switch (GetTextEffect())
                    {
                    case TE_NONE:
                        pass->SetPixelShaderDefines("SIGNED_DISTANCE_FIELD");
                        break;

                    case TE_SHADOW:
                        pass->SetPixelShaderDefines("SIGNED_DISTANCE_FIELD TEXT_EFFECT_SHADOW");
                        break;

                    case TE_STROKE:
                        pass->SetPixelShaderDefines("SIGNED_DISTANCE_FIELD TEXT_EFFECT_STROKE");
                        break;
                    }
                }

                pass->SetBlendMode(BLEND_ALPHA);
                pass->SetDepthWrite(false);
                material->SetTechnique(0, tech);
                material->SetCullMode(CULL_NONE);
                batches_[i].material_ = material;
            }
            else
                batches_[i].material_ = material_->Clone();
        }

        Material* material = batches_[i].material_;
        Texture* texture = uiBatches_[i].texture_;
        material->SetTexture(TU_DIFFUSE, texture);

        if (GetFont()->IsSDFFont())
        {
            switch (GetTextEffect())
            {
            case TE_SHADOW:
                if (texture)
                {
                    Vector2 shadowOffset(0.5f / texture->GetWidth(), 0.5f / texture->GetHeight());
                    material->SetShaderParameter("ShadowOffset", shadowOffset);
                }
                material->SetShaderParameter("ShadowColor", GetEffectColor());
                break;

            case TE_STROKE:
                material->SetShaderParameter("StrokeColor", GetEffectColor());
                break;

            default:
                break;
            }
        }
    }
}
Пример #7
0
TTFFontShadowAndStroke::TTFFontShadowAndStroke()
{
    auto layer = LayerColor::create(Color4B(0,190,0,255));
    addChild(layer, -10);
    
    auto s = Director::getInstance()->getWinSize();
    
    Color3B tintColorRed(  255, 0, 0   );
    Color3B tintColorYellow( 255, 255, 0 );
    Color3B tintColorBlue( 0, 0, 255   );
    Color3B strokeColor( 0, 10, 255  );
    Color3B strokeShadowColor( 255, 0, 0   );
    
    Size shadowOffset(12.0, 12.0);
    
    FontDefinition shadowTextDef;
    shadowTextDef._fontSize = 20;
    shadowTextDef._fontName = std::string("Marker Felt");
    
    shadowTextDef._shadow._shadowEnabled = true;
    shadowTextDef._shadow._shadowOffset  = shadowOffset;
    shadowTextDef._shadow._shadowOpacity = 1.0;
    shadowTextDef._shadow._shadowBlur    = 1.0;
    shadowTextDef._fontFillColor   = tintColorRed;
    
    // shadow only label
    auto fontShadow = LabelTTF::createWithFontDefinition("Shadow Only Red Text", shadowTextDef);
    
    // add label to the scene
    this->addChild(fontShadow);
    fontShadow->setPosition(Point(s.width/2,s.height/4*2.5));
    

    // create the stroke only label
    FontDefinition strokeTextDef;
    strokeTextDef._fontSize = 20;
    strokeTextDef._fontName = std::string("Marker Felt");
    
    strokeTextDef._stroke._strokeEnabled = true;
    strokeTextDef._stroke._strokeColor   = strokeColor;
    strokeTextDef._stroke._strokeSize    = 1.5;
    
    strokeTextDef._fontFillColor   = tintColorYellow;
    
    // stroke only label
    auto fontStroke = LabelTTF::createWithFontDefinition("Stroke Only Yellow Text", strokeTextDef);
    
    // add label to the scene
    this->addChild(fontStroke);
    fontStroke->setPosition(Point(s.width/2,s.height/4*1.8));
    
    
    
    // create the label stroke and shadow
    FontDefinition strokeShaodwTextDef;
    strokeShaodwTextDef._fontSize = 20;
    strokeShaodwTextDef._fontName = std::string("Marker Felt");
    
    strokeShaodwTextDef._stroke._strokeEnabled = true;
    strokeShaodwTextDef._stroke._strokeColor   = strokeShadowColor;
    strokeShaodwTextDef._stroke._strokeSize    = 1.5;
    
    strokeShaodwTextDef._shadow._shadowEnabled = true;
    strokeShaodwTextDef._shadow._shadowOffset  = shadowOffset;
    strokeShaodwTextDef._shadow._shadowOpacity = 1.0;
    strokeShaodwTextDef._shadow._shadowBlur    = 1.0;
    
    
    strokeShaodwTextDef._fontFillColor   = tintColorBlue;
    
    // shadow + stroke label
    auto fontStrokeAndShadow = LabelTTF::createWithFontDefinition("Stroke & Shadow Blue Text", strokeShaodwTextDef);
    
    // add label to the scene
    this->addChild(fontStrokeAndShadow);
    fontStrokeAndShadow->setPosition(Point(s.width/2,s.height/4*1.1));
}
Пример #8
0
void MythPainter::DrawTextPriv(MythImage *im, const QString &msg, int flags,
                               const QRect &r, const MythFontProperties &font)
{
    if (!im)
        return;

    QColor outlineColor;
    int outlineSize = 0;
    int outlineAlpha;
    if (font.hasOutline())
        font.GetOutline(outlineColor, outlineSize, outlineAlpha);

    QPoint shadowOffset(0, 0);
    QColor shadowColor;
    int shadowAlpha;
    if (font.hasShadow())
        font.GetShadow(shadowOffset, shadowColor, shadowAlpha);

    QFontMetrics fm(font.face());
    int totalHeight = fm.height() + outlineSize +
        std::max(outlineSize, std::abs(shadowOffset.y()));

    // initialPaddingX is the number of pixels from the left of the
    // input QRect to the left of the actual text.  It is always 0
    // because we don't add padding to the text rectangle.
    int initialPaddingX = 0;

    // initialPaddingY is the number of pixels from the top of the
    // input QRect to the top of the actual text.  It may be nonzero
    // because of extra vertical padding.
    int initialPaddingY = (r.height() - totalHeight) / 2;
    // Hack.  Normally we vertically center the text due to some
    // (solvable) issues in the SubtitleScreen code - the text rect
    // and the background rect are both created with PAD_WIDTH extra
    // padding, and to honor Qt::AlignTop, the text rect needs to be
    // without padding.  This doesn't work for Qt::TextWordWrap, since
    // the first line will be vertically centered with subsequence
    // lines below.  So if Qt::TextWordWrap is set, we do top
    // alignment.
    if (flags & Qt::TextWordWrap)
        initialPaddingY = 0;

    // textOffsetX is the number of pixels from r.left() to the left
    // edge of the core text.  This assumes that flags contains
    // Qt::AlignLeft.
    int textOffsetX =
        initialPaddingX + std::max(outlineSize, -shadowOffset.x());

    // textOffsetY is the number of pixels from r.top() to the top
    // edge of the core text.  This assumes that flags contains
    // Qt::AlignTop.
    int textOffsetY =
        initialPaddingY + std::max(outlineSize, -shadowOffset.y());

    QImage pm(r.size(), QImage::Format_ARGB32);
    QColor fillcolor = font.color();
    if (font.hasOutline())
        fillcolor = outlineColor;
    fillcolor.setAlpha(0);
    pm.fill(fillcolor.rgba());

    QPainter tmp(&pm);
    QFont tmpfont = font.face();
    tmpfont.setStyleStrategy(QFont::OpenGLCompatible);
    tmp.setFont(tmpfont);

    QPainterPath path;
    if (font.hasOutline())
        path.addText(0, 0, tmpfont, msg);

    if (font.hasShadow())
    {
        QRect a = QRect(0, 0, r.width(), r.height());
        a.translate(shadowOffset.x() + textOffsetX,
                    shadowOffset.y() + textOffsetY);

        shadowColor.setAlpha(shadowAlpha);
        tmp.setPen(shadowColor);
        tmp.drawText(a, flags, msg);
    }

    if (font.hasOutline())
    {
        // QPainter::drawText() treats the Y coordinate as the top of
        // the text (when Qt::AlignTop is used).  However,
        // QPainterPath::addText() treats the Y coordinate as the base
        // line of the text.  To translate from the top to the base
        // line, we need to add QFontMetrics::ascent().
        int adjX = 0;
        int adjY = fm.ascent();

        outlineColor.setAlpha(outlineAlpha);
        tmp.setPen(outlineColor);

        path.translate(adjX + textOffsetX, adjY + textOffsetY);
        QPen pen = tmp.pen();
        pen.setWidth(outlineSize * 2 + 1);
        pen.setCapStyle(Qt::RoundCap);
        pen.setJoinStyle(Qt::RoundJoin);
        tmp.setPen(pen);
        tmp.drawPath(path);

        path.translate(outlineSize, outlineSize);
    }

    tmp.setPen(QPen(font.GetBrush(), 0));
    tmp.setBrush(font.GetBrush());
    tmp.drawText(textOffsetX, textOffsetY, r.width(), r.height(),
                 flags, msg);
    tmp.end();
    im->Assign(pm);
}
Пример #9
0
void KoShadowConfigWidget::offsetChanged()
{
    emit shadowOffsetChanged( shadowOffset() );
}
Пример #10
0
void Text3D::UpdateTextMaterials(bool forceUpdate)
{
    Font* font = GetFont();
    bool isSDFFont = font ? font->IsSDFFont() : false;

    batches_.Resize(uiBatches_.Size());
    geometries_.Resize(uiBatches_.Size());

    for (unsigned i = 0; i < batches_.Size(); ++i)
    {
        if (!geometries_[i])
        {
            Geometry* geometry = new Geometry(context_);
            geometry->SetVertexBuffer(0, vertexBuffer_);
            batches_[i].geometry_ = geometries_[i] = geometry;
        }

        if (!batches_[i].material_ || forceUpdate || isSDFFont != usingSDFShader_)
        {
            // If material not defined, create a reasonable default from scratch
            if (!material_)
            {
                Material* material = new Material(context_);
                Technique* tech = new Technique(context_);
                Pass* pass = tech->CreatePass("alpha");
                pass->SetVertexShader("Text");
                pass->SetPixelShader("Text");

                if (isSDFFont)
                {
                    switch (GetTextEffect())
                    {
                    case TE_NONE:
                        pass->SetPixelShaderDefines("SIGNED_DISTANCE_FIELD");
                        break;

                    case TE_SHADOW:
                        pass->SetPixelShaderDefines("SIGNED_DISTANCE_FIELD TEXT_EFFECT_SHADOW");
                        break;

                    case TE_STROKE:
                        pass->SetPixelShaderDefines("SIGNED_DISTANCE_FIELD TEXT_EFFECT_STROKE");
                        break;
                    }
                }

                pass->SetBlendMode(BLEND_ALPHA);
                pass->SetDepthWrite(false);
                material->SetTechnique(0, tech);
                material->SetCullMode(CULL_NONE);
                batches_[i].material_ = material;
            }
            else
                batches_[i].material_ = material_->Clone();

            // Note: custom material is assumed to use the right kind of shader; it is not modified to define SIGNED_DISTANCE_FIELD
            usingSDFShader_ = isSDFFont;
        }

        Material* material = batches_[i].material_;
        Texture* texture = uiBatches_[i].texture_;
        material->SetTexture(TU_DIFFUSE, texture);

        if (isSDFFont)
        {
            switch (GetTextEffect())
            {
            case TE_SHADOW:
                if (texture)
                {
                    Vector2 shadowOffset(0.5f / texture->GetWidth(), 0.5f / texture->GetHeight());
                    material->SetShaderParameter("ShadowOffset", shadowOffset);
                }
                material->SetShaderParameter("ShadowColor", GetEffectColor());
                break;

            case TE_STROKE:
                material->SetShaderParameter("StrokeColor", GetEffectColor());
                break;

            default:
                break;
            }
        }
    }
}
Пример #11
0
TTFFontShadowAndStroke::TTFFontShadowAndStroke()
{
    auto layer = LayerColor::create(Color4B(0,190,0,255));
    addChild(layer, -10);
    
    auto s = Director::getInstance()->getWinSize();
    
    Color3B tintColorRed(  255, 0, 0   );
    Color3B tintColorYellow( 255, 255, 0 );
    Color3B tintColorBlue( 0, 0, 255   );
    Color3B strokeColor( 0, 0, 255  );
    Color3B strokeShadowColor( 255, 0, 0   );
    
    Size shadowOffset(12.0, 12.0);
    
    FontDefinition shadowTextDef;
    shadowTextDef._fontSize = 20;
    shadowTextDef._fontName = std::string("Marker Felt");
    
    shadowTextDef._shadow._shadowEnabled = true;
    shadowTextDef._shadow._shadowOffset  = shadowOffset;
    shadowTextDef._shadow._shadowOpacity = 1.0;
    shadowTextDef._shadow._shadowBlur    = 1.0;
    shadowTextDef._fontFillColor   = tintColorRed;
    
    // shadow only label
    auto fontShadow = LabelTTF::createWithFontDefinition("Shadow Only Red Text", shadowTextDef);
    
    // add label to the scene
    this->addChild(fontShadow);
    fontShadow->setPosition(Vec2(s.width/2,s.height/4*2.5));
    

    // create the stroke only label
    FontDefinition strokeTextDef;
    strokeTextDef._fontSize = 20;
    strokeTextDef._fontName = std::string("Marker Felt");
    
    strokeTextDef._stroke._strokeEnabled = true;
    strokeTextDef._stroke._strokeColor   = strokeColor;
    strokeTextDef._stroke._strokeSize    = 1.5;
    
    strokeTextDef._fontFillColor   = tintColorYellow;
    
    // stroke only label
    auto fontStroke = LabelTTF::createWithFontDefinition("Stroke Only Yellow Text", strokeTextDef);
    
    // add label to the scene
    this->addChild(fontStroke);
    fontStroke->setPosition(Vec2(s.width/2,s.height/4*1.8));
    
    
    
    // create the label stroke and shadow
    FontDefinition strokeShaodwTextDef;
    strokeShaodwTextDef._fontSize = 20;
    strokeShaodwTextDef._fontName = std::string("Marker Felt");
    
    strokeShaodwTextDef._stroke._strokeEnabled = true;
    strokeShaodwTextDef._stroke._strokeColor   = strokeShadowColor;
    strokeShaodwTextDef._stroke._strokeSize    = 1.5;
    
    strokeShaodwTextDef._shadow._shadowEnabled = true;
    strokeShaodwTextDef._shadow._shadowOffset  = shadowOffset;
    strokeShaodwTextDef._shadow._shadowOpacity = 1.0;
    strokeShaodwTextDef._shadow._shadowBlur    = 1.0;
    
    
    strokeShaodwTextDef._fontFillColor   = tintColorBlue;
    
    // shadow + stroke label
    auto fontStrokeAndShadow = LabelTTF::createWithFontDefinition("Stroke & Shadow Blue Text", strokeShaodwTextDef);
    
    // add label to the scene
    this->addChild(fontStrokeAndShadow);
    fontStrokeAndShadow->setPosition(Vec2(s.width/2,s.height/4*1.1));
    
    auto buttonBG = MenuItemImage::create("cocosui/animationbuttonnormal.png", "cocosui/animationbuttonpressed.png");
    buttonBG->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT);
    buttonBG->setPosition(VisibleRect::left());
    
    // create the label stroke and shadow
    strokeShaodwTextDef._fontSize = 18;
    strokeShaodwTextDef._fontName = "Marker Felt";
    
    strokeShaodwTextDef._stroke._strokeEnabled = true;
    strokeShaodwTextDef._stroke._strokeColor   = Color3B::BLACK;
    strokeShaodwTextDef._stroke._strokeSize    = 3.0f;
    
    strokeShaodwTextDef._shadow._shadowEnabled = false;
    strokeShaodwTextDef._shadow._shadowOffset  = Size(1, 1);
    strokeShaodwTextDef._shadow._shadowOpacity = 1.0;
    strokeShaodwTextDef._shadow._shadowBlur    = 0.5f;
    
    strokeShaodwTextDef._fontFillColor   = Color3B::WHITE;
    
    // shadow + stroke label
    fontStrokeAndShadow = LabelTTF::createWithFontDefinition("Test", strokeShaodwTextDef);
    
    // add label to the scene
    buttonBG->addChild(fontStrokeAndShadow);
    fontStrokeAndShadow->setPosition(Vec2(buttonBG->getContentSize().width/2, buttonBG->getContentSize().height/2));
    
    auto menu = Menu::create(buttonBG, nullptr);
    menu->setAnchorPoint(Vec2::ANCHOR_BOTTOM_LEFT);
    menu->setPosition(Vec2::ZERO);
    addChild(menu);
}