<commit_before>/*!
 * \file text.cpp
 * \brief file text.cpp
 *
 * Copyright 2013 by Nomovok Ltd.
 *
 * Contact: info@nomovok.com
 *
 * This Source Code Form is subject to the
 * terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with
 * this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * \author Kevin Rogovin <kevin.rogovin@nomovok.com>
 *
 */

#include "WRATHConfig.hpp"
#include <fstream>
#include <iomanip>
#include <limits>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>

#include "vecN.hpp"
#include "WRATHNew.hpp"
#include "WRATHmalloc.hpp"
#include "WRATHUtil.hpp"
#include "WRATHTextureFontFreeType_Mix.hpp"
#include "WRATHFontFetch.hpp"
#include "WRATHLayerItemWidgetsTranslate.hpp"
#include "WRATHTime.hpp"

#include "ngl_backend.hpp"
#include "wrath_demo.hpp"

/*!
\details
This example demonstrates the basic usage of the \ref Text
Module API for the typical "hello world" example.
 */

class cmd_line_type:public DemoKernelMaker
{
public:
  command_line_argument_value<int> m_virtual_height, m_virtual_width, m_layer_count;
  command_line_argument_value<bool> m_gradient, m_blend;

  cmd_line_type(void):
    m_virtual_height(128, "virtual_height", "Virtual height to which to scale display", *this),
    m_virtual_width(256, "virtual_width", "Virtual width to which to scale display", *this),
    m_layer_count(100, "layer_count", "# of full screen blends underneath text", *this),
    m_gradient(true, "gradient", "if true, layers are painted with a radial gradient", *this),
    m_blend(true, "blend", "if true, layers are blended", *this)
  {}

  virtual
  DemoKernel*
  make_demo(void);

  virtual
  void
  delete_demo(DemoKernel *k)
  {
    if(k!=NULL)
      {
        WRATHDelete(k);
      }
  }
};

class CounterExample:public DemoKernel
{
public:
  CounterExample(cmd_line_type *cmd_line);
  ~CounterExample();

  void resize(int width, int height);
  virtual void handle_event(FURYEvent::handle ev);
  virtual void paint(void);

private:
  typedef WRATHLayerTranslateFamilySet FamilySet;

  typedef FamilySet::PlainFamily::TextWidget TextWidget;
  typedef FamilySet::ColorRadialGradientFamily::RectWidget RectGradientWidget;
  typedef FamilySet::ColorFamily::RectWidget RectWidget;

  WRATHTripleBufferEnabler::handle m_tr;
  WRATHLayer *m_layer;
  WRATHLayer *m_child_layer;

  unsigned int m_frame;
  WRATHTime m_time, m_total_time;
  unsigned int m_virtual_height;

  WRATHGradient *m_gradient;

  std::vector<RectWidget*> m_rects;
  std::vector<RectGradientWidget*> m_gradient_rects;
  TextWidget *m_text_widget;
};

DemoKernel*
cmd_line_type::
make_demo(void)
{
  return WRATHNew CounterExample(this);
}

CounterExample::
CounterExample(cmd_line_type *cmd_line):
  DemoKernel(cmd_line),
  m_layer(NULL),
  m_frame(0),
  m_text_widget(0)
{
  /*
    Create the WRATHTripleBufferEnabler object
    which our visual items will use to sync
   */
  m_tr=WRATHNew WRATHTripleBufferEnabler();

  /*
    Create the WRATHLayer which will contain and
    draw our shape
   */
  m_layer=WRATHNew WRATHLayer(m_tr);

  m_child_layer=WRATHNew WRATHLayer(m_layer);

  /*
    these are the transforms that will be
    applied to all elements contained in the
    WRATHLayer:

    + a 3D transform
    + a Projection transform

    For the purpose of this example the 3D transform
    will be the identity matrix. In other words no
    transform will be applied to the vertex data.

    Projection will be orthographic
    */

  float_orthogonal_projection_params proj_params(0, cmd_line->m_virtual_width.m_value,
                                                 cmd_line->m_virtual_height.m_value, 0);

  m_virtual_height=cmd_line->m_virtual_height.m_value;
  m_layer->simulation_matrix(WRATHLayer::projection_matrix, float4x4(proj_params));

  /*
    create the text widget
   */
  m_text_widget=WRATHNew TextWidget(m_layer, WRATHTextItemTypes::text_opaque_non_aa);
  m_text_widget->z_order(-1);

  /*
    add the text to the text widget
   */
  m_text_widget->position(vec2(0.0f, 0.0f));

  WRATHDrawType draw_type;
  if(cmd_line->m_blend.m_value)
    {
      draw_type=WRATHDrawType::transparent_pass();
    }
  else
    {
      draw_type=WRATHDrawType::opaque_pass();
    }

  if(cmd_line->m_gradient.m_value)
    {
      m_gradient=WRATHNew WRATHGradient("my little gradient");
      m_gradient->set_color(0.00f, WRATHGradient::color(1.0f, 0.0f, 0.0f, 1.0f));
      m_gradient->set_color(0.25f, WRATHGradient::color(0.0f, 1.0f, 0.0f, 1.0f));
      m_gradient->set_color(0.50f, WRATHGradient::color(0.0f, 0.0f, 1.0f, 1.0f));
      m_gradient->set_color(0.75f, WRATHGradient::color(1.0f, 1.0f, 1.0f, 1.0f));

      //create the brush, the node type specifies the shader
      WRATHBrush brush(type_tag<RectGradientWidget::Node>(), m_gradient);

      //create the drawer from the brush
      RectGradientWidget::Drawer drawer(brush, draw_type);

      if(cmd_line->m_blend.m_value)
        {
          //specify how blending is done on the rect items.
          drawer.m_draw_passes[0]
            .m_draw_state.add_gl_state_change(WRATHNew WRATHGLStateChange::blend_state(GL_SRC_ALPHA, GL_ONE));
        }

      m_gradient_rects.resize(std::max(0, cmd_line->m_layer_count.m_value));
      for(unsigned int i=0, endi=m_gradient_rects.size(); i<endi ; ++i)
	{
	  m_gradient_rects[i]=WRATHNew RectGradientWidget(m_child_layer, drawer);
	  m_gradient_rects[i]->color(WRATHGradient::color(1.0f, 1.0f, 1.0f, 0.2f));
	  m_gradient_rects[i]->z_order(i);
	  m_gradient_rects[i]->properties()
	    ->set_parameters(WRATHDefaultRectAttributePacker::rect_properties(cmd_line->m_virtual_width.m_value,
									      cmd_line->m_virtual_height.m_value));
	}
    }
  else
    {
      m_gradient=NULL;

      //create the brush, the node type specifies the shader
      type_tag<RectWidget::Node> tag;
      WRATHBrush brush(tag);
      RectWidget::Drawer drawer(brush, draw_type);

      m_rects.resize(std::max(0, cmd_line->m_layer_count.m_value));
      for(unsigned int i=0, endi=m_rects.size(); i<endi ; ++i)
	{
	  m_rects[i]=WRATHNew RectWidget(m_child_layer, drawer);
	  m_rects[i]->color(WRATHGradient::color(1.0f, 1.0f, 1.0f, 0.2f));
	  m_rects[i]->z_order(i);
	  m_rects[i]->properties()->set_parameters(WRATHDefaultRectAttributePacker::rect_properties(cmd_line->m_virtual_width.m_value,
												    cmd_line->m_virtual_height.m_value));
	}
    }

}

CounterExample::~CounterExample()
{
  if(m_layer!=NULL)
    {
      WRATHPhasedDelete(m_layer);
    }

  /*
    Delete all resources
   */
  WRATHResourceManagerBase::clear_all_resource_managers();

  /*
    purge cleanup to perform post processing cleanup
    tasks(typically deletion of GL objects).
   */
  m_tr->purge_cleanup();
  m_tr=NULL;
}

void CounterExample::resize(int width, int height)
{
  glViewport(0, 0, width, height);
}

void CounterExample::paint(void)
{
  WRATHTextDataStream stream;
  int32_t ms, total_ms;

  if(m_frame==0)
    {
      ms=total_ms=0;
      m_time.restart();
      m_total_time.restart();
    }
  else
    {
      ms=m_time.restart();
      total_ms=m_total_time.elapsed();
    }

  stream.stream() << WRATHText::set_pixel_size(64)
                  << WRATHText::set_color(255, 0, 0)
                  << WRATHText::set_font(WRATHFontDatabase::FontProperties()
                                         .family_name("DejaVuSans"),
                                         type_tag<WRATHTextureFontFreeType_Analytic>())
                  << m_frame
                  << "\n" << ms << " ms\n";

  m_text_widget->clear();
  m_text_widget->add_text(stream);

  for(unsigned int i=0, endi=m_gradient_rects.size(); i<endi ; ++i)
    {
      vec2 p;
      float r0, r1, theta, d;

      theta=(static_cast<float>(total_ms)/500.0f + static_cast<float>(i+1)/4.0f) * 2.0f * float(M_PI);
      d=static_cast<float>(i+1)/static_cast<float>(endi) * static_cast<float>(m_virtual_height) * 0.5f;
      p.x()=d*cosf(theta) + d;
      p.y()=d*sinf(theta) + d;
      r0=0.0f;
      r1=(sinf(0.1f*theta)+2.0f)*static_cast<float>(m_virtual_height) * 0.1f;
      m_gradient_rects[i]->set_gradient(p, r0, p, r1);
    }

  m_tr->signal_complete_simulation_frame();
  m_tr->signal_begin_presentation_frame();
  m_layer->clear_and_draw();

  ++m_frame;
  update_widget();
}

void CounterExample::handle_event(FURYEvent::handle ev)
{
  if(ev->type()==FURYEvent::Resize)
    {
      FURYResizeEvent::handle rev(ev.static_cast_handle<FURYResizeEvent>());
      resize(rev->new_size().x(), rev->new_size().y());
    }
  else if(ev->type()==FURYEvent::KeyUp)
    {
      FURYKeyEvent::handle qe(ev.static_cast_handle<FURYKeyEvent>());
      if(qe->key().m_value == FURYKey_Escape || qe->key().m_value == FURYKey_Q)
        {
          end_demo();
        }
    }
}

int main(int argc, char **argv)
{
    cmd_line_type cmd_line;
    return cmd_line.main(argc, argv);
}
<commit_msg>let brush better handle shader magicks<commit_after>/*!
 * \file text.cpp
 * \brief file text.cpp
 *
 * Copyright 2013 by Nomovok Ltd.
 *
 * Contact: info@nomovok.com
 *
 * This Source Code Form is subject to the
 * terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with
 * this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * \author Kevin Rogovin <kevin.rogovin@nomovok.com>
 *
 */

#include "WRATHConfig.hpp"
#include <fstream>
#include <iomanip>
#include <limits>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>

#include "vecN.hpp"
#include "WRATHNew.hpp"
#include "WRATHmalloc.hpp"
#include "WRATHUtil.hpp"
#include "WRATHTextureFontFreeType_Mix.hpp"
#include "WRATHFontFetch.hpp"
#include "WRATHLayerItemWidgetsTranslate.hpp"
#include "WRATHTime.hpp"

#include "ngl_backend.hpp"
#include "wrath_demo.hpp"

/*!
\details
This example demonstrates the basic usage of the \ref Text
Module API for the typical "hello world" example.
 */

class cmd_line_type:public DemoKernelMaker
{
public:
  command_line_argument_value<int> m_virtual_height, m_virtual_width, m_layer_count;
  command_line_argument_value<bool> m_gradient, m_blend;

  cmd_line_type(void):
    m_virtual_height(128, "virtual_height", "Virtual height to which to scale display", *this),
    m_virtual_width(256, "virtual_width", "Virtual width to which to scale display", *this),
    m_layer_count(100, "layer_count", "# of full screen blends underneath text", *this),
    m_gradient(true, "gradient", "if true, layers are painted with a radial gradient", *this),
    m_blend(true, "blend", "if true, layers are blended", *this)
  {}

  virtual
  DemoKernel*
  make_demo(void);

  virtual
  void
  delete_demo(DemoKernel *k)
  {
    if(k!=NULL)
      {
        WRATHDelete(k);
      }
  }
};

class CounterExample:public DemoKernel
{
public:
  CounterExample(cmd_line_type *cmd_line);
  ~CounterExample();

  void resize(int width, int height);
  virtual void handle_event(FURYEvent::handle ev);
  virtual void paint(void);

private:
  typedef WRATHLayerTranslateFamilySet FamilySet;

  typedef FamilySet::PlainFamily::TextWidget TextWidget;
  typedef FamilySet::ColorRadialGradientFamily::RectWidget RectWidget;

  WRATHTripleBufferEnabler::handle m_tr;
  WRATHLayer *m_layer;
  WRATHLayer *m_child_layer;

  unsigned int m_frame;
  WRATHTime m_time, m_total_time;
  unsigned int m_virtual_height;

  WRATHGradient *m_gradient;

  std::vector<RectWidget*> m_rects;
  TextWidget *m_text_widget;
};

DemoKernel*
cmd_line_type::
make_demo(void)
{
  return WRATHNew CounterExample(this);
}

CounterExample::
CounterExample(cmd_line_type *cmd_line):
  DemoKernel(cmd_line),
  m_layer(NULL),
  m_frame(0),
  m_text_widget(0)
{
  /*
    Create the WRATHTripleBufferEnabler object
    which our visual items will use to sync
   */
  m_tr=WRATHNew WRATHTripleBufferEnabler();

  /*
    Create the WRATHLayer which will contain and
    draw our shape
   */
  m_layer=WRATHNew WRATHLayer(m_tr);

  m_child_layer=WRATHNew WRATHLayer(m_layer);

  /*
    these are the transforms that will be
    applied to all elements contained in the
    WRATHLayer:

    + a 3D transform
    + a Projection transform

    For the purpose of this example the 3D transform
    will be the identity matrix. In other words no
    transform will be applied to the vertex data.

    Projection will be orthographic
    */

  float_orthogonal_projection_params proj_params(0, cmd_line->m_virtual_width.m_value,
                                                 cmd_line->m_virtual_height.m_value, 0);

  m_virtual_height=cmd_line->m_virtual_height.m_value;
  m_layer->simulation_matrix(WRATHLayer::projection_matrix, float4x4(proj_params));

  /*
    create the text widget
   */
  m_text_widget=WRATHNew TextWidget(m_layer, WRATHTextItemTypes::text_opaque_non_aa);
  m_text_widget->z_order(-1);

  /*
    add the text to the text widget
   */
  m_text_widget->position(vec2(0.0f, 0.0f));

  WRATHDrawType draw_type;
  if(cmd_line->m_blend.m_value)
    {
      draw_type=WRATHDrawType::transparent_pass();
    }
  else
    {
      draw_type=WRATHDrawType::opaque_pass();
    }

  if(cmd_line->m_gradient.m_value)
    {
      m_gradient=WRATHNew WRATHGradient("my little gradient");
      m_gradient->set_color(0.00f, WRATHGradient::color(1.0f, 0.0f, 0.0f, 1.0f));
      m_gradient->set_color(0.25f, WRATHGradient::color(0.0f, 1.0f, 0.0f, 1.0f));
      m_gradient->set_color(0.50f, WRATHGradient::color(0.0f, 0.0f, 1.0f, 1.0f));
      m_gradient->set_color(0.75f, WRATHGradient::color(1.0f, 1.0f, 1.0f, 1.0f));
    }
  else
    {
      m_gradient=NULL;
    }

  //create the brush, the node type specifies the shader
  WRATHBrush brush(type_tag<RectWidget::Node>(), m_gradient);

  //create the drawer from the brush
  RectWidget::Drawer drawer(brush, draw_type);

  if(cmd_line->m_blend.m_value)
    {
      //specify how blending is done on the rect items.
      drawer.m_draw_passes[0]
        .m_draw_state.add_gl_state_change(WRATHNew WRATHGLStateChange::blend_state(GL_SRC_ALPHA, GL_ONE));
    }

  m_rects.resize(std::max(0, cmd_line->m_layer_count.m_value));
  for(unsigned int i=0, endi=m_rects.size(); i<endi ; ++i)
    {
      m_rects[i]=WRATHNew RectWidget(m_child_layer, drawer);
      m_rects[i]->color(WRATHGradient::color(1.0f, 1.0f, 1.0f, 0.2f));
      m_rects[i]->z_order(i);
      m_rects[i]->properties()
        ->set_parameters(WRATHDefaultRectAttributePacker::rect_properties(cmd_line->m_virtual_width.m_value,
                                                                          cmd_line->m_virtual_height.m_value));
    }

}

CounterExample::~CounterExample()
{
  if(m_layer!=NULL)
    {
      WRATHPhasedDelete(m_layer);
    }

  /*
    Delete all resources
   */
  WRATHResourceManagerBase::clear_all_resource_managers();

  /*
    purge cleanup to perform post processing cleanup
    tasks(typically deletion of GL objects).
   */
  m_tr->purge_cleanup();
  m_tr=NULL;
}

void CounterExample::resize(int width, int height)
{
  glViewport(0, 0, width, height);
}

void CounterExample::paint(void)
{
  WRATHTextDataStream stream;
  int32_t ms, total_ms;

  if(m_frame==0)
    {
      ms=total_ms=0;
      m_time.restart();
      m_total_time.restart();
    }
  else
    {
      ms=m_time.restart();
      total_ms=m_total_time.elapsed();
    }

  stream.stream() << WRATHText::set_pixel_size(64)
                  << WRATHText::set_color(255, 0, 0)
                  << WRATHText::set_font(WRATHFontDatabase::FontProperties()
                                         .family_name("DejaVuSans"),
                                         type_tag<WRATHTextureFontFreeType_Analytic>())
                  << m_frame
                  << "\n" << ms << " ms\n";

  m_text_widget->clear();
  m_text_widget->add_text(stream);

  for(unsigned int i=0, endi=m_rects.size(); i<endi ; ++i)
    {
      vec2 p;
      float r0, r1, theta, d;

      theta=(static_cast<float>(total_ms)/500.0f + static_cast<float>(i+1)/4.0f) * 2.0f * float(M_PI);
      d=static_cast<float>(i+1)/static_cast<float>(endi) * static_cast<float>(m_virtual_height) * 0.5f;
      p.x()=d*cosf(theta) + d;
      p.y()=d*sinf(theta) + d;
      r0=0.0f;
      r1=(sinf(0.1f*theta)+2.0f)*static_cast<float>(m_virtual_height) * 0.1f;
      m_rects[i]->set_gradient(p, r0, p, r1);
    }

  m_tr->signal_complete_simulation_frame();
  m_tr->signal_begin_presentation_frame();
  m_layer->clear_and_draw();

  ++m_frame;
  update_widget();
}

void CounterExample::handle_event(FURYEvent::handle ev)
{
  if(ev->type()==FURYEvent::Resize)
    {
      FURYResizeEvent::handle rev(ev.static_cast_handle<FURYResizeEvent>());
      resize(rev->new_size().x(), rev->new_size().y());
    }
  else if(ev->type()==FURYEvent::KeyUp)
    {
      FURYKeyEvent::handle qe(ev.static_cast_handle<FURYKeyEvent>());
      if(qe->key().m_value == FURYKey_Escape || qe->key().m_value == FURYKey_Q)
        {
          end_demo();
        }
    }
}

int main(int argc, char **argv)
{
    cmd_line_type cmd_line;
    return cmd_line.main(argc, argv);
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/glsl/GrGLSLProgramBuilder.h"

#include "src/gpu/GrCaps.h"
#include "src/gpu/GrPipeline.h"
#include "src/gpu/GrRenderTarget.h"
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/GrTexturePriv.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
#include "src/gpu/glsl/GrGLSLVarying.h"
#include "src/gpu/glsl/GrGLSLXferProcessor.h"
#include "src/sksl/SkSLCompiler.h"

const int GrGLSLProgramBuilder::kVarsPerBlock = 8;

GrGLSLProgramBuilder::GrGLSLProgramBuilder(GrRenderTarget* renderTarget,
                                           const GrProgramDesc& desc,
                                           const GrProgramInfo& programInfo)
        : fVS(this)
        , fGS(this)
        , fFS(this)
        , fStageIndex(-1)
        , fRenderTarget(renderTarget)
        , fDesc(desc)
        , fProgramInfo(programInfo)
        , fGeometryProcessor(nullptr)
        , fXferProcessor(nullptr)
        , fNumFragmentSamplers(0) {}

void GrGLSLProgramBuilder::addFeature(GrShaderFlags shaders,
                                      uint32_t featureBit,
                                      const char* extensionName) {
    if (shaders & kVertex_GrShaderFlag) {
        fVS.addFeature(featureBit, extensionName);
    }
    if (shaders & kGeometry_GrShaderFlag) {
        SkASSERT(this->primitiveProcessor().willUseGeoShader());
        fGS.addFeature(featureBit, extensionName);
    }
    if (shaders & kFragment_GrShaderFlag) {
        fFS.addFeature(featureBit, extensionName);
    }
}

bool GrGLSLProgramBuilder::emitAndInstallProcs() {
    // First we loop over all of the installed processors and collect coord transforms.  These will
    // be sent to the GrGLSLPrimitiveProcessor in its emitCode function
    SkString inputColor;
    SkString inputCoverage;
    this->emitAndInstallPrimProc(&inputColor, &inputCoverage);
    this->emitAndInstallFragProcs(&inputColor, &inputCoverage);
    this->emitAndInstallXferProc(inputColor, inputCoverage);
    fGeometryProcessor->emitTransformCode(&fVS, this->uniformHandler());

    return this->checkSamplerCounts();
}

void GrGLSLProgramBuilder::emitAndInstallPrimProc(SkString* outputColor, SkString* outputCoverage) {
    const GrPrimitiveProcessor& proc = this->primitiveProcessor();

    // Program builders have a bit of state we need to clear with each effect
    AutoStageAdvance adv(this);
    this->nameExpression(outputColor, "outputColor");
    this->nameExpression(outputCoverage, "outputCoverage");

    SkASSERT(!fUniformHandles.fRTAdjustmentUni.isValid());
    GrShaderFlags rtAdjustVisibility;
    if (proc.willUseGeoShader()) {
        rtAdjustVisibility = kGeometry_GrShaderFlag;
    } else if (proc.willUseTessellationShaders()) {
        rtAdjustVisibility = kTessEvaluation_GrShaderFlag;
    } else {
        rtAdjustVisibility = kVertex_GrShaderFlag;
    }
    fUniformHandles.fRTAdjustmentUni = this->uniformHandler()->addUniform(
            nullptr, rtAdjustVisibility, kFloat4_GrSLType, SkSL::Compiler::RTADJUST_NAME);
    const char* rtAdjustName =
        this->uniformHandler()->getUniformCStr(fUniformHandles.fRTAdjustmentUni);

    // Enclose custom code in a block to avoid namespace conflicts
    SkString openBrace;
    openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
    fFS.codeAppend(openBrace.c_str());
    fVS.codeAppendf("// Primitive Processor %s\n", proc.name());

    SkASSERT(!fGeometryProcessor);
    fGeometryProcessor.reset(proc.createGLSLInstance(*this->shaderCaps()));

    SkAutoSTMalloc<4, SamplerHandle> texSamplers(proc.numTextureSamplers());
    for (int i = 0; i < proc.numTextureSamplers(); ++i) {
        SkString name;
        name.printf("TextureSampler_%d", i);
        const auto& sampler = proc.textureSampler(i);
        texSamplers[i] = this->emitSampler(proc.textureSampler(i).backendFormat(),
                                           sampler.samplerState(),
                                           sampler.swizzle(),
                                           name.c_str());
    }

    GrGLSLPrimitiveProcessor::FPCoordTransformHandler transformHandler(this->pipeline(),
                                                                       &fTransformedCoordVars);
    GrGLSLGeometryProcessor::EmitArgs args(&fVS,
                                           proc.willUseGeoShader() ? &fGS : nullptr,
                                           &fFS,
                                           this->varyingHandler(),
                                           this->uniformHandler(),
                                           this->shaderCaps(),
                                           proc,
                                           outputColor->c_str(),
                                           outputCoverage->c_str(),
                                           rtAdjustName,
                                           texSamplers.get(),
                                           &transformHandler);
    fGeometryProcessor->emitCode(args);

    // We have to check that effects and the code they emit are consistent, ie if an effect
    // asks for dst color, then the emit code needs to follow suit
    SkDEBUGCODE(verify(proc);)

    fFS.codeAppend("}");
}

void GrGLSLProgramBuilder::emitAndInstallFragProcs(SkString* color, SkString* coverage) {
    int transformedCoordVarsIdx = 0;
    SkString** inOut = &color;
    SkSTArray<8, std::unique_ptr<GrGLSLFragmentProcessor>> glslFragmentProcessors;
    for (int i = 0; i < this->pipeline().numFragmentProcessors(); ++i) {
        if (i == this->pipeline().numColorFragmentProcessors()) {
            inOut = &coverage;
        }
        SkString output;
        const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i);
        output = this->emitAndInstallFragProc(fp, i, transformedCoordVarsIdx, **inOut, output,
                                              &glslFragmentProcessors);
        for (const auto& subFP : GrFragmentProcessor::FPCRange(fp)) {
            transformedCoordVarsIdx += subFP.numCoordTransforms();
        }
        **inOut = output;
    }
    fFragmentProcessorCnt = glslFragmentProcessors.count();
    fFragmentProcessors.reset(new std::unique_ptr<GrGLSLFragmentProcessor>[fFragmentProcessorCnt]);
    for (int i = 0; i < fFragmentProcessorCnt; ++i) {
        fFragmentProcessors[i] = std::move(glslFragmentProcessors[i]);
    }
}

// TODO Processors cannot output zeros because an empty string is all 1s
// the fix is to allow effects to take the SkString directly
SkString GrGLSLProgramBuilder::emitAndInstallFragProc(
        const GrFragmentProcessor& fp,
        int index,
        int transformedCoordVarsIdx,
        const SkString& input,
        SkString output,
        SkTArray<std::unique_ptr<GrGLSLFragmentProcessor>>* glslFragmentProcessors) {
    SkASSERT(input.size());
    // Program builders have a bit of state we need to clear with each effect
    AutoStageAdvance adv(this);
    this->nameExpression(&output, "output");

    // Enclose custom code in a block to avoid namespace conflicts
    SkString openBrace;
    openBrace.printf("{ // Stage %d, %s\n", fStageIndex, fp.name());
    fFS.codeAppend(openBrace.c_str());

    GrGLSLFragmentProcessor* fragProc = fp.createGLSLInstance();

    SkSTArray<4, SamplerHandle> texSamplers;
    int samplerIdx = 0;
    for (const auto& subFP : GrFragmentProcessor::FPCRange(fp)) {
        for (int i = 0; i < subFP.numTextureSamplers(); ++i) {
            SkString name;
            name.printf("TextureSampler_%d", samplerIdx++);
            const auto& sampler = subFP.textureSampler(i);
            texSamplers.emplace_back(this->emitSampler(sampler.view().proxy()->backendFormat(),
                                                       sampler.samplerState(),
                                                       sampler.view().swizzle(),
                                                       name.c_str()));
        }
    }
    const GrGLSLPrimitiveProcessor::TransformVar* coordVars = fTransformedCoordVars.begin() +
                                                              transformedCoordVarsIdx;
    GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars);
    GrGLSLFragmentProcessor::TextureSamplers textureSamplers(&fp, texSamplers.begin());
    GrGLSLFragmentProcessor::EmitArgs args(&fFS,
                                           this->uniformHandler(),
                                           this->shaderCaps(),
                                           fp,
                                           output.c_str(),
                                           input.c_str(),
                                           coords,
                                           textureSamplers);

    fragProc->emitCode(args);

    // We have to check that effects and the code they emit are consistent, ie if an effect
    // asks for dst color, then the emit code needs to follow suit
    SkDEBUGCODE(verify(fp);)
    glslFragmentProcessors->emplace_back(fragProc);

    fFS.codeAppend("}");
    return output;
}

void GrGLSLProgramBuilder::emitAndInstallXferProc(const SkString& colorIn,
                                                  const SkString& coverageIn) {
    // Program builders have a bit of state we need to clear with each effect
    AutoStageAdvance adv(this);

    SkASSERT(!fXferProcessor);
    const GrXferProcessor& xp = this->pipeline().getXferProcessor();
    fXferProcessor.reset(xp.createGLSLInstance());

    // Enable dual source secondary output if we have one
    if (xp.hasSecondaryOutput()) {
        fFS.enableSecondaryOutput();
    }

    if (this->shaderCaps()->mustDeclareFragmentShaderOutput()) {
        fFS.enableCustomOutput();
    }

    SkString openBrace;
    openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
    fFS.codeAppend(openBrace.c_str());

    SamplerHandle dstTextureSamplerHandle;
    GrSurfaceOrigin dstTextureOrigin = kTopLeft_GrSurfaceOrigin;

    const GrSurfaceProxyView& dstView = this->pipeline().dstProxyView();
    if (GrTextureProxy* dstTextureProxy = dstView.asTextureProxy()) {
        // GrProcessor::TextureSampler sampler(dstTexture);
        const GrSwizzle& swizzle = dstView.swizzle();
        dstTextureSamplerHandle = this->emitSampler(dstTextureProxy->backendFormat(),
                                                    GrSamplerState(), swizzle, "DstTextureSampler");
        dstTextureOrigin = dstView.origin();
        SkASSERT(dstTextureProxy->textureType() != GrTextureType::kExternal);
    }

    SkString finalInColor = colorIn.size() ? colorIn : SkString("float4(1)");

    GrGLSLXferProcessor::EmitArgs args(&fFS,
                                       this->uniformHandler(),
                                       this->shaderCaps(),
                                       xp,
                                       finalInColor.c_str(),
                                       coverageIn.size() ? coverageIn.c_str() : "float4(1)",
                                       fFS.getPrimaryColorOutputName(),
                                       fFS.getSecondaryColorOutputName(),
                                       dstTextureSamplerHandle,
                                       dstTextureOrigin,
                                       this->pipeline().writeSwizzle());
    fXferProcessor->emitCode(args);

    // We have to check that effects and the code they emit are consistent, ie if an effect
    // asks for dst color, then the emit code needs to follow suit
    SkDEBUGCODE(verify(xp);)
    fFS.codeAppend("}");
}

GrGLSLProgramBuilder::SamplerHandle GrGLSLProgramBuilder::emitSampler(
        const GrBackendFormat& backendFormat, GrSamplerState state, const GrSwizzle& swizzle,
        const char* name) {
    ++fNumFragmentSamplers;
    return this->uniformHandler()->addSampler(backendFormat, state, swizzle, name,
                                              this->shaderCaps());
}

bool GrGLSLProgramBuilder::checkSamplerCounts() {
    const GrShaderCaps& shaderCaps = *this->shaderCaps();
    if (fNumFragmentSamplers > shaderCaps.maxFragmentSamplers()) {
        GrCapsDebugf(this->caps(), "Program would use too many fragment samplers\n");
        return false;
    }
    return true;
}

#ifdef SK_DEBUG
void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
    SkASSERT(!fFS.fHasReadDstColorThisStage_DebugOnly);
    SkASSERT(fFS.fUsedProcessorFeaturesThisStage_DebugOnly == gp.requestedFeatures());
}

void GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) {
    SkASSERT(!fFS.fHasReadDstColorThisStage_DebugOnly);
    SkASSERT(fFS.fUsedProcessorFeaturesThisStage_DebugOnly == fp.requestedFeatures());
}

void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) {
    SkASSERT(xp.willReadDstColor() == fFS.fHasReadDstColorThisStage_DebugOnly);
    SkASSERT(fFS.fUsedProcessorFeaturesThisStage_DebugOnly == xp.requestedFeatures());
}
#endif

void GrGLSLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name, bool mangle) {
    if ('\0' == prefix) {
        *out = name;
    } else {
        out->printf("%c%s", prefix, name);
    }
    if (mangle) {
        if (out->endsWith('_')) {
            // Names containing "__" are reserved.
            out->append("x");
        }
        out->appendf("_Stage%d%s", fStageIndex, fFS.getMangleString().c_str());
    }
}

void GrGLSLProgramBuilder::nameExpression(SkString* output, const char* baseName) {
    // create var to hold stage result.  If we already have a valid output name, just use that
    // otherwise create a new mangled one.  This name is only valid if we are reordering stages
    // and have to tell stage exactly where to put its output.
    SkString outName;
    if (output->size()) {
        outName = output->c_str();
    } else {
        this->nameVariable(&outName, '\0', baseName);
    }
    fFS.codeAppendf("half4 %s;", outName.c_str());
    *output = outName;
}

void GrGLSLProgramBuilder::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
    this->uniformHandler()->appendUniformDecls(visibility, out);
}

void GrGLSLProgramBuilder::addRTWidthUniform(const char* name) {
    SkASSERT(!fUniformHandles.fRTWidthUni.isValid());
    GrGLSLUniformHandler* uniformHandler = this->uniformHandler();
    fUniformHandles.fRTWidthUni =
            uniformHandler->internalAddUniformArray(nullptr, kFragment_GrShaderFlag, kHalf_GrSLType,
                                                    name, false, 0, nullptr);
}

void GrGLSLProgramBuilder::addRTHeightUniform(const char* name) {
    SkASSERT(!fUniformHandles.fRTHeightUni.isValid());
    GrGLSLUniformHandler* uniformHandler = this->uniformHandler();
    fUniformHandles.fRTHeightUni =
            uniformHandler->internalAddUniformArray(nullptr, kFragment_GrShaderFlag, kHalf_GrSLType,
                                                    name, false, 0, nullptr);
}

void GrGLSLProgramBuilder::finalizeShaders() {
    this->varyingHandler()->finalize();
    fVS.finalize(kVertex_GrShaderFlag);
    if (this->primitiveProcessor().willUseGeoShader()) {
        SkASSERT(this->shaderCaps()->geometryShaderSupport());
        fGS.finalize(kGeometry_GrShaderFlag);
    }
    fFS.finalize(kFragment_GrShaderFlag);
}
<commit_msg>Put top level FPs into their own functions<commit_after>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/glsl/GrGLSLProgramBuilder.h"

#include "src/gpu/GrCaps.h"
#include "src/gpu/GrPipeline.h"
#include "src/gpu/GrRenderTarget.h"
#include "src/gpu/GrShaderCaps.h"
#include "src/gpu/GrTexturePriv.h"
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
#include "src/gpu/glsl/GrGLSLVarying.h"
#include "src/gpu/glsl/GrGLSLXferProcessor.h"
#include "src/sksl/SkSLCompiler.h"

const int GrGLSLProgramBuilder::kVarsPerBlock = 8;

GrGLSLProgramBuilder::GrGLSLProgramBuilder(GrRenderTarget* renderTarget,
                                           const GrProgramDesc& desc,
                                           const GrProgramInfo& programInfo)
        : fVS(this)
        , fGS(this)
        , fFS(this)
        , fStageIndex(-1)
        , fRenderTarget(renderTarget)
        , fDesc(desc)
        , fProgramInfo(programInfo)
        , fGeometryProcessor(nullptr)
        , fXferProcessor(nullptr)
        , fNumFragmentSamplers(0) {}

void GrGLSLProgramBuilder::addFeature(GrShaderFlags shaders,
                                      uint32_t featureBit,
                                      const char* extensionName) {
    if (shaders & kVertex_GrShaderFlag) {
        fVS.addFeature(featureBit, extensionName);
    }
    if (shaders & kGeometry_GrShaderFlag) {
        SkASSERT(this->primitiveProcessor().willUseGeoShader());
        fGS.addFeature(featureBit, extensionName);
    }
    if (shaders & kFragment_GrShaderFlag) {
        fFS.addFeature(featureBit, extensionName);
    }
}

bool GrGLSLProgramBuilder::emitAndInstallProcs() {
    // First we loop over all of the installed processors and collect coord transforms.  These will
    // be sent to the GrGLSLPrimitiveProcessor in its emitCode function
    SkString inputColor;
    SkString inputCoverage;
    this->emitAndInstallPrimProc(&inputColor, &inputCoverage);
    this->emitAndInstallFragProcs(&inputColor, &inputCoverage);
    this->emitAndInstallXferProc(inputColor, inputCoverage);
    fGeometryProcessor->emitTransformCode(&fVS, this->uniformHandler());

    return this->checkSamplerCounts();
}

void GrGLSLProgramBuilder::emitAndInstallPrimProc(SkString* outputColor, SkString* outputCoverage) {
    const GrPrimitiveProcessor& proc = this->primitiveProcessor();

    // Program builders have a bit of state we need to clear with each effect
    AutoStageAdvance adv(this);
    this->nameExpression(outputColor, "outputColor");
    this->nameExpression(outputCoverage, "outputCoverage");

    SkASSERT(!fUniformHandles.fRTAdjustmentUni.isValid());
    GrShaderFlags rtAdjustVisibility;
    if (proc.willUseGeoShader()) {
        rtAdjustVisibility = kGeometry_GrShaderFlag;
    } else if (proc.willUseTessellationShaders()) {
        rtAdjustVisibility = kTessEvaluation_GrShaderFlag;
    } else {
        rtAdjustVisibility = kVertex_GrShaderFlag;
    }
    fUniformHandles.fRTAdjustmentUni = this->uniformHandler()->addUniform(
            nullptr, rtAdjustVisibility, kFloat4_GrSLType, SkSL::Compiler::RTADJUST_NAME);
    const char* rtAdjustName =
        this->uniformHandler()->getUniformCStr(fUniformHandles.fRTAdjustmentUni);

    // Enclose custom code in a block to avoid namespace conflicts
    SkString openBrace;
    openBrace.printf("{ // Stage %d, %s\n", fStageIndex, proc.name());
    fFS.codeAppend(openBrace.c_str());
    fVS.codeAppendf("// Primitive Processor %s\n", proc.name());

    SkASSERT(!fGeometryProcessor);
    fGeometryProcessor.reset(proc.createGLSLInstance(*this->shaderCaps()));

    SkAutoSTMalloc<4, SamplerHandle> texSamplers(proc.numTextureSamplers());
    for (int i = 0; i < proc.numTextureSamplers(); ++i) {
        SkString name;
        name.printf("TextureSampler_%d", i);
        const auto& sampler = proc.textureSampler(i);
        texSamplers[i] = this->emitSampler(proc.textureSampler(i).backendFormat(),
                                           sampler.samplerState(),
                                           sampler.swizzle(),
                                           name.c_str());
    }

    GrGLSLPrimitiveProcessor::FPCoordTransformHandler transformHandler(this->pipeline(),
                                                                       &fTransformedCoordVars);
    GrGLSLGeometryProcessor::EmitArgs args(&fVS,
                                           proc.willUseGeoShader() ? &fGS : nullptr,
                                           &fFS,
                                           this->varyingHandler(),
                                           this->uniformHandler(),
                                           this->shaderCaps(),
                                           proc,
                                           outputColor->c_str(),
                                           outputCoverage->c_str(),
                                           rtAdjustName,
                                           texSamplers.get(),
                                           &transformHandler);
    fGeometryProcessor->emitCode(args);

    // We have to check that effects and the code they emit are consistent, ie if an effect
    // asks for dst color, then the emit code needs to follow suit
    SkDEBUGCODE(verify(proc);)

    fFS.codeAppend("}");
}

void GrGLSLProgramBuilder::emitAndInstallFragProcs(SkString* color, SkString* coverage) {
    int transformedCoordVarsIdx = 0;
    SkString** inOut = &color;
    SkSTArray<8, std::unique_ptr<GrGLSLFragmentProcessor>> glslFragmentProcessors;
    for (int i = 0; i < this->pipeline().numFragmentProcessors(); ++i) {
        if (i == this->pipeline().numColorFragmentProcessors()) {
            inOut = &coverage;
        }
        SkString output;
        const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i);
        output = this->emitAndInstallFragProc(fp, i, transformedCoordVarsIdx, **inOut, output,
                                              &glslFragmentProcessors);
        for (const auto& subFP : GrFragmentProcessor::FPCRange(fp)) {
            transformedCoordVarsIdx += subFP.numCoordTransforms();
        }
        **inOut = output;
    }
    fFragmentProcessorCnt = glslFragmentProcessors.count();
    fFragmentProcessors.reset(new std::unique_ptr<GrGLSLFragmentProcessor>[fFragmentProcessorCnt]);
    for (int i = 0; i < fFragmentProcessorCnt; ++i) {
        fFragmentProcessors[i] = std::move(glslFragmentProcessors[i]);
    }
}

// TODO Processors cannot output zeros because an empty string is all 1s
// the fix is to allow effects to take the SkString directly
SkString GrGLSLProgramBuilder::emitAndInstallFragProc(
        const GrFragmentProcessor& fp,
        int index,
        int transformedCoordVarsIdx,
        const SkString& input,
        SkString output,
        SkTArray<std::unique_ptr<GrGLSLFragmentProcessor>>* glslFragmentProcessors) {
    SkASSERT(input.size());
    // Program builders have a bit of state we need to clear with each effect
    AutoStageAdvance adv(this);
    this->nameExpression(&output, "output");

    GrGLSLFragmentProcessor* fragProc = fp.createGLSLInstance();

    SkSTArray<4, SamplerHandle> texSamplers;
    int samplerIdx = 0;
    for (const auto& subFP : GrFragmentProcessor::FPCRange(fp)) {
        for (int i = 0; i < subFP.numTextureSamplers(); ++i) {
            SkString name;
            name.printf("TextureSampler_%d", samplerIdx++);
            const auto& sampler = subFP.textureSampler(i);
            texSamplers.emplace_back(this->emitSampler(sampler.view().proxy()->backendFormat(),
                                                       sampler.samplerState(),
                                                       sampler.view().swizzle(),
                                                       name.c_str()));
        }
    }
    const GrGLSLPrimitiveProcessor::TransformVar* coordVars = fTransformedCoordVars.begin() +
                                                              transformedCoordVarsIdx;
    GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars);
    GrGLSLFragmentProcessor::TextureSamplers textureSamplers(&fp, texSamplers.begin());
    GrGLSLFragmentProcessor::EmitArgs args(&fFS,
                                           this->uniformHandler(),
                                           this->shaderCaps(),
                                           fp,
                                           "_output",
                                           "_input",
                                           coords,
                                           textureSamplers);

    auto name = fFS.writeProcessorFunction(fragProc, args);
    fFS.codeAppendf("%s = %s(%s);", output.c_str(), name.c_str(), input.c_str());

    // We have to check that effects and the code they emit are consistent, ie if an effect
    // asks for dst color, then the emit code needs to follow suit
    SkDEBUGCODE(verify(fp);)
    glslFragmentProcessors->emplace_back(fragProc);

    return output;
}

void GrGLSLProgramBuilder::emitAndInstallXferProc(const SkString& colorIn,
                                                  const SkString& coverageIn) {
    // Program builders have a bit of state we need to clear with each effect
    AutoStageAdvance adv(this);

    SkASSERT(!fXferProcessor);
    const GrXferProcessor& xp = this->pipeline().getXferProcessor();
    fXferProcessor.reset(xp.createGLSLInstance());

    // Enable dual source secondary output if we have one
    if (xp.hasSecondaryOutput()) {
        fFS.enableSecondaryOutput();
    }

    if (this->shaderCaps()->mustDeclareFragmentShaderOutput()) {
        fFS.enableCustomOutput();
    }

    SkString openBrace;
    openBrace.printf("{ // Xfer Processor: %s\n", xp.name());
    fFS.codeAppend(openBrace.c_str());

    SamplerHandle dstTextureSamplerHandle;
    GrSurfaceOrigin dstTextureOrigin = kTopLeft_GrSurfaceOrigin;

    const GrSurfaceProxyView& dstView = this->pipeline().dstProxyView();
    if (GrTextureProxy* dstTextureProxy = dstView.asTextureProxy()) {
        // GrProcessor::TextureSampler sampler(dstTexture);
        const GrSwizzle& swizzle = dstView.swizzle();
        dstTextureSamplerHandle = this->emitSampler(dstTextureProxy->backendFormat(),
                                                    GrSamplerState(), swizzle, "DstTextureSampler");
        dstTextureOrigin = dstView.origin();
        SkASSERT(dstTextureProxy->textureType() != GrTextureType::kExternal);
    }

    SkString finalInColor = colorIn.size() ? colorIn : SkString("float4(1)");

    GrGLSLXferProcessor::EmitArgs args(&fFS,
                                       this->uniformHandler(),
                                       this->shaderCaps(),
                                       xp,
                                       finalInColor.c_str(),
                                       coverageIn.size() ? coverageIn.c_str() : "float4(1)",
                                       fFS.getPrimaryColorOutputName(),
                                       fFS.getSecondaryColorOutputName(),
                                       dstTextureSamplerHandle,
                                       dstTextureOrigin,
                                       this->pipeline().writeSwizzle());
    fXferProcessor->emitCode(args);

    // We have to check that effects and the code they emit are consistent, ie if an effect
    // asks for dst color, then the emit code needs to follow suit
    SkDEBUGCODE(verify(xp);)
    fFS.codeAppend("}");
}

GrGLSLProgramBuilder::SamplerHandle GrGLSLProgramBuilder::emitSampler(
        const GrBackendFormat& backendFormat, GrSamplerState state, const GrSwizzle& swizzle,
        const char* name) {
    ++fNumFragmentSamplers;
    return this->uniformHandler()->addSampler(backendFormat, state, swizzle, name,
                                              this->shaderCaps());
}

bool GrGLSLProgramBuilder::checkSamplerCounts() {
    const GrShaderCaps& shaderCaps = *this->shaderCaps();
    if (fNumFragmentSamplers > shaderCaps.maxFragmentSamplers()) {
        GrCapsDebugf(this->caps(), "Program would use too many fragment samplers\n");
        return false;
    }
    return true;
}

#ifdef SK_DEBUG
void GrGLSLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
    SkASSERT(!fFS.fHasReadDstColorThisStage_DebugOnly);
    SkASSERT(fFS.fUsedProcessorFeaturesThisStage_DebugOnly == gp.requestedFeatures());
}

void GrGLSLProgramBuilder::verify(const GrFragmentProcessor& fp) {
    SkASSERT(!fFS.fHasReadDstColorThisStage_DebugOnly);
    SkASSERT(fFS.fUsedProcessorFeaturesThisStage_DebugOnly == fp.requestedFeatures());
}

void GrGLSLProgramBuilder::verify(const GrXferProcessor& xp) {
    SkASSERT(xp.willReadDstColor() == fFS.fHasReadDstColorThisStage_DebugOnly);
    SkASSERT(fFS.fUsedProcessorFeaturesThisStage_DebugOnly == xp.requestedFeatures());
}
#endif

void GrGLSLProgramBuilder::nameVariable(SkString* out, char prefix, const char* name, bool mangle) {
    if ('\0' == prefix) {
        *out = name;
    } else {
        out->printf("%c%s", prefix, name);
    }
    if (mangle) {
        if (out->endsWith('_')) {
            // Names containing "__" are reserved.
            out->append("x");
        }
        out->appendf("_Stage%d%s", fStageIndex, fFS.getMangleString().c_str());
    }
}

void GrGLSLProgramBuilder::nameExpression(SkString* output, const char* baseName) {
    // create var to hold stage result.  If we already have a valid output name, just use that
    // otherwise create a new mangled one.  This name is only valid if we are reordering stages
    // and have to tell stage exactly where to put its output.
    SkString outName;
    if (output->size()) {
        outName = output->c_str();
    } else {
        this->nameVariable(&outName, '\0', baseName);
    }
    fFS.codeAppendf("half4 %s;", outName.c_str());
    *output = outName;
}

void GrGLSLProgramBuilder::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
    this->uniformHandler()->appendUniformDecls(visibility, out);
}

void GrGLSLProgramBuilder::addRTWidthUniform(const char* name) {
    SkASSERT(!fUniformHandles.fRTWidthUni.isValid());
    GrGLSLUniformHandler* uniformHandler = this->uniformHandler();
    fUniformHandles.fRTWidthUni =
            uniformHandler->internalAddUniformArray(nullptr, kFragment_GrShaderFlag, kHalf_GrSLType,
                                                    name, false, 0, nullptr);
}

void GrGLSLProgramBuilder::addRTHeightUniform(const char* name) {
    SkASSERT(!fUniformHandles.fRTHeightUni.isValid());
    GrGLSLUniformHandler* uniformHandler = this->uniformHandler();
    fUniformHandles.fRTHeightUni =
            uniformHandler->internalAddUniformArray(nullptr, kFragment_GrShaderFlag, kHalf_GrSLType,
                                                    name, false, 0, nullptr);
}

void GrGLSLProgramBuilder::finalizeShaders() {
    this->varyingHandler()->finalize();
    fVS.finalize(kVertex_GrShaderFlag);
    if (this->primitiveProcessor().willUseGeoShader()) {
        SkASSERT(this->shaderCaps()->geometryShaderSupport());
        fGS.finalize(kGeometry_GrShaderFlag);
    }
    fFS.finalize(kFragment_GrShaderFlag);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: userinstall.cxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: lo $ $Date: 2004-07-28 15:02:07 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source 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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2003 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "userinstall.hxx"
#include "langselect.hxx"

#include <stdio.h>

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif
#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _OSL_FILE_HXX_
#include <osl/file.hxx>
#endif
#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif
#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _VOS_SECURITY_HXX_
#include <vos/security.hxx>
#endif
#ifndef _VOS_REF_HXX_
#include <vos/ref.hxx>
#endif
#ifndef _VOS_PROCESS_HXX_
#include <vos/process.hxx>
#endif

#ifndef _TOOLS_RESMGR_HXX_
#include <tools/resmgr.hxx>
#endif

#ifndef _UTL_BOOTSTRAP_HXX
#include <unotools/bootstrap.hxx>
#endif

#ifndef _SVTOOLS_LANGUAGEOPTIONS_HXX
#include <svtools/languageoptions.hxx>
#endif
#ifndef _SVTOOLS_SYSLOCALEOPTIONSOPTIONS_HXX
#include <svtools/syslocaleoptions.hxx>
#endif

#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <tools/isolang.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/util/XChangesBatch.hpp>
#include <com/sun/star/beans/XHierarchicalPropertySet.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/XLocalizable.hpp>
#include <com/sun/star/lang/Locale.hpp>

#include "app.hxx"

using namespace rtl;
using namespace osl;
using namespace utl;
using namespace com::sun::star::container;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::beans;
using namespace com::sun::star::util;

namespace desktop {

    static UserInstall::UserInstallError create_user_install(OUString&);

    static bool is_user_install()
    {
        try
        {
            OUString sConfigSrvc(
                 RTL_CONSTASCII_USTRINGPARAM(
                    "com.sun.star.configuration.ConfigurationProvider" ) );
            OUString sAccessSrvc(
                 RTL_CONSTASCII_USTRINGPARAM(
                    "com.sun.star.configuration.ConfigurationAccess" ) );

            // get configuration provider
            Reference< XMultiServiceFactory > theMSF
                = comphelper::getProcessServiceFactory();
            Reference< XMultiServiceFactory > theConfigProvider
                = Reference< XMultiServiceFactory >(
                    theMSF->createInstance(sConfigSrvc), UNO_QUERY_THROW);

            // localize the provider to user selection
//            Reference< XLocalizable > localizable(theConfigProvider, UNO_QUERY_THROW);
//            LanguageType aUserLanguageType = LanguageSelection::getLanguageType();
//            OUString aUserLanguage = ConvertLanguageToIsoString(aUserLanguageType);
//            Locale aLocale = LanguageSelection::IsoStringToLocale(aUserLanguage);
//            localizable->setLocale(aLocale);

            Reference< XLocalizable > localizable(theConfigProvider, UNO_QUERY_THROW);
            OUString aUserLanguage = LanguageSelection::getLanguageString();
            Locale aLocale = LanguageSelection::IsoStringToLocale(aUserLanguage);
            localizable->setLocale(aLocale);

            Sequence< Any > theArgs(1);
            NamedValue v;
            v.Name = OUString::createFromAscii("NodePath");
            v.Value = makeAny(OUString::createFromAscii("org.openoffice.Setup"));
            theArgs[0] <<= v;
            Reference< XHierarchicalNameAccess> hnacc(
                theConfigProvider->createInstanceWithArguments(
                    sAccessSrvc, theArgs), UNO_QUERY_THROW);

            try
            {
                sal_Bool bValue = sal_False;
                hnacc->getByHierarchicalName(
                        OUString( RTL_CONSTASCII_USTRINGPARAM(
                            "Office/ooSetupInstCompleted" ) ) ) >>= bValue;

                return bValue ? true : false;
            }
            catch ( NoSuchElementException const & )
            {
                // just return false in this case.
            }
        }
        catch (Exception const & e)
        {
            OString msg(OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US));
            OSL_ENSURE(sal_False, msg.getStr());
        }

        return false;
    }

    UserInstall::UserInstallError UserInstall::finalize()
    {
        OUString aUserInstallPath;
        Bootstrap::PathStatus aLocateResult =
            Bootstrap::locateUserInstallation(aUserInstallPath);

        switch (aLocateResult) {

            case Bootstrap::DATA_INVALID:
            case Bootstrap::DATA_MISSING:
            case Bootstrap::DATA_UNKNOWN:
                // cannot find a valid path or path is missing
                return E_Unknown;

            case Bootstrap::PATH_EXISTS:
            {
                // path exists, check if an installation lives there
                if ( is_user_install() )
                {
                    return E_None;
                }
                // Note: fall-thru intended.
            }
            case Bootstrap::PATH_VALID:
                // found a path but need to create user install
                return create_user_install(aUserInstallPath);
            default:
                return E_Unknown;
        }
    }

    static osl::FileBase::RC copy_recursive( const rtl::OUString& srcUnqPath, const rtl::OUString& dstUnqPath)
    {

        FileBase::RC err;
        DirectoryItem aDirItem;
        DirectoryItem::get(srcUnqPath, aDirItem);
        FileStatus aFileStatus(FileStatusMask_All);
        aDirItem.getFileStatus(aFileStatus);

        if( aFileStatus.getFileType() == FileStatus::Directory)
        {
            // create directory if not already there
            err = Directory::create( dstUnqPath );
            if (err == osl::FileBase::E_EXIST)
                err = osl::FileBase::E_None;

            FileBase::RC next = err;
            if (err == osl::FileBase::E_None)
            {
                // iterate through directory contents
                Directory aDir( srcUnqPath );
                aDir.open();
                while (err ==  osl::FileBase::E_None &&
                    (next = aDir.getNextItem( aDirItem )) == osl::FileBase::E_None)
                {
                    aDirItem.getFileStatus(aFileStatus);
                    // generate new src/dst pair and make recursive call
                    rtl::OUString newSrcUnqPath = aFileStatus.getFileURL();
                    rtl::OUString newDstUnqPath = dstUnqPath;
                    rtl::OUString itemname = aFileStatus.getFileName();
                    // append trailing '/' if needed
                    if (newDstUnqPath.lastIndexOf(sal_Unicode('/')) != newDstUnqPath.getLength()-1)
                        newDstUnqPath += rtl::OUString::createFromAscii("/");
                    newDstUnqPath += itemname;
                    // recursion
                    err = copy_recursive(newSrcUnqPath, newDstUnqPath);
                }
                aDir.close();
                if( next != FileBase::E_NOENT ) err = FileBase::E_INVAL;
            }
        }
        else
        {
            // copy single file - foldback
            err = File::copy( srcUnqPath,dstUnqPath );
        }
        return err;
    }

    static const char *pszCopyList[] = {
        "/user",
        NULL
    };

    UserInstall::UserInstallError UserInstall::configureLanguage()
    {
        try
        {
            OUString sConfigSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
            OUString sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");

            // get configuration provider
            Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory();

            OUString aUserLanguage = LanguageSelection::getLanguageString();

            Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >(
                theMSF->createInstance(sConfigSrvc), UNO_QUERY_THROW);

            // localize the provider to user selection
            Reference< XLocalizable > localizable(theConfigProvider, UNO_QUERY_THROW);
            Locale aLocale = LanguageSelection::IsoStringToLocale(aUserLanguage);
            localizable->setLocale(aLocale);

            // org.openoffice.Setup/L10N/ooLocale
            // org.openoffice.Office.Linguistic/General/DefaultLocale
            // org.openoffice.Office.Linguistic/General/DefaultLocale_CJK

            Sequence< Any > theArgs(1);
            NamedValue v;
            v.Name = OUString::createFromAscii("NodePath");
            v.Value <<= OUString::createFromAscii("org.openoffice.Office.Linguistic/General");
            theArgs[0] <<= v;
            Reference< XPropertySet > pset = Reference< XPropertySet >(
                theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW);
            if (aUserLanguage.equalsAscii("ja") || aUserLanguage.equalsAscii("ko")
                || aUserLanguage.equalsAscii("zh-CN") || aUserLanguage.equalsAscii("zh-TW"))
            {
                pset->setPropertyValue(OUString::createFromAscii("DefaultLocale"), makeAny(OUString::createFromAscii("en-US")));
                pset->setPropertyValue(OUString::createFromAscii("DefaultLocale_CJK"), makeAny(aUserLanguage));
            } else
            {
                pset->setPropertyValue(OUString::createFromAscii("DefaultLocale"), makeAny(aUserLanguage));
            }
            Reference< XChangesBatch >(pset, UNO_QUERY_THROW)->commitChanges();

            v.Value = makeAny(OUString::createFromAscii("org.openoffice.Setup"));
            theArgs[0] <<= v;
            Reference< XHierarchicalPropertySet> hpset(
                theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW);
            hpset->setHierarchicalPropertyValue(OUString::createFromAscii("L10N/ooLocale"), makeAny(aUserLanguage));
            Reference< XChangesBatch >(hpset, UNO_QUERY_THROW)->commitChanges();

        } catch (Exception const & e)
        {
            OString msg(OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US));
            OSL_ENSURE(sal_False, msg.getStr());
            return UserInstall::E_Configuration;
        }

        // everything went well
        return UserInstall::E_None;
    }

    static UserInstall::UserInstallError create_user_install(OUString& aUserPath)
    {
        OUString aBasePath;
        if (Bootstrap::locateBaseInstallation(aBasePath) != Bootstrap::PATH_EXISTS)
            return UserInstall::E_InvalidBaseinstall;

        // create the user directory
        FileBase::RC rc = Directory::create(aUserPath);
        if ((rc != FileBase::E_None) && (rc != FileBase::E_EXIST)) return UserInstall::E_Creation;

            // copy data from shared data directory of base installation
        for (sal_Int32 i=0; pszCopyList[i]!=NULL; i++)
        {
            rc = copy_recursive(
                    aBasePath + OUString::createFromAscii(pszCopyList[i]),
                    aUserPath + OUString::createFromAscii(pszCopyList[i]));
            if ((rc != FileBase::E_None) && (rc != FileBase::E_EXIST)) return UserInstall::E_Creation;
        }
        try
        {
            OUString sConfigSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
            OUString sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");

            // get configuration provider
            Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory();
            Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >(
                theMSF->createInstance(sConfigSrvc), UNO_QUERY_THROW);
            Sequence< Any > theArgs(1);
            NamedValue v(OUString::createFromAscii("NodePath"), makeAny(OUString::createFromAscii("org.openoffice.Setup")));
            //v.Name = OUString::createFromAscii("NodePath");
            //v.Value = makeAny(OUString::createFromAscii("org.openoffice.Setup"));
            theArgs[0] <<= v;
            Reference< XHierarchicalPropertySet> hpset(
                theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW);
            hpset->setHierarchicalPropertyValue(OUString::createFromAscii("Office/ooSetupInstCompleted"), makeAny(sal_True));
            Reference< XChangesBatch >(hpset, UNO_QUERY_THROW)->commitChanges();
        }
        catch (Exception&)
        {
            return UserInstall::E_Creation;
        }

        return UserInstall::E_None;

    }
}
<commit_msg>INTEGRATION: CWS migration1 (1.13.20); FILE MERGED 2004/10/27 14:51:18 lo 1.13.20.2: #116053# change /user -> /presets 2004/08/30 12:54:02 lo 1.13.20.1: #i33255# first start wizard<commit_after>/*************************************************************************
 *
 *  $RCSfile: userinstall.cxx,v $
 *
 *  $Revision: 1.14 $
 *
 *  last change: $Author: obo $ $Date: 2004-11-15 15:46:40 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source 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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2003 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "userinstall.hxx"
#include "langselect.hxx"

#include <stdio.h>

#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif
#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _OSL_FILE_HXX_
#include <osl/file.hxx>
#endif
#ifndef _OSL_MUTEX_HXX_
#include <osl/mutex.hxx>
#endif
#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _VOS_SECURITY_HXX_
#include <vos/security.hxx>
#endif
#ifndef _VOS_REF_HXX_
#include <vos/ref.hxx>
#endif
#ifndef _VOS_PROCESS_HXX_
#include <vos/process.hxx>
#endif

#ifndef _TOOLS_RESMGR_HXX_
#include <tools/resmgr.hxx>
#endif

#ifndef _UTL_BOOTSTRAP_HXX
#include <unotools/bootstrap.hxx>
#endif

#ifndef _SVTOOLS_LANGUAGEOPTIONS_HXX
#include <svtools/languageoptions.hxx>
#endif
#ifndef _SVTOOLS_SYSLOCALEOPTIONSOPTIONS_HXX
#include <svtools/syslocaleoptions.hxx>
#endif

#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <tools/isolang.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/util/XChangesBatch.hpp>
#include <com/sun/star/beans/XHierarchicalPropertySet.hpp>
#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/lang/XLocalizable.hpp>
#include <com/sun/star/lang/Locale.hpp>

#include "app.hxx"

using namespace rtl;
using namespace osl;
using namespace utl;
using namespace com::sun::star::container;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::beans;
using namespace com::sun::star::util;

namespace desktop {

    static UserInstall::UserInstallError create_user_install(OUString&);

    static bool is_user_install()
    {
        try
        {
            OUString sConfigSrvc(
                 RTL_CONSTASCII_USTRINGPARAM(
                    "com.sun.star.configuration.ConfigurationProvider" ) );
            OUString sAccessSrvc(
                 RTL_CONSTASCII_USTRINGPARAM(
                    "com.sun.star.configuration.ConfigurationAccess" ) );

            // get configuration provider
            Reference< XMultiServiceFactory > theMSF
                = comphelper::getProcessServiceFactory();
            Reference< XMultiServiceFactory > theConfigProvider
                = Reference< XMultiServiceFactory >(
                    theMSF->createInstance(sConfigSrvc), UNO_QUERY_THROW);

            // localize the provider to user selection
//            Reference< XLocalizable > localizable(theConfigProvider, UNO_QUERY_THROW);
//            LanguageType aUserLanguageType = LanguageSelection::getLanguageType();
//            OUString aUserLanguage = ConvertLanguageToIsoString(aUserLanguageType);
//            Locale aLocale = LanguageSelection::IsoStringToLocale(aUserLanguage);
//            localizable->setLocale(aLocale);

            Reference< XLocalizable > localizable(theConfigProvider, UNO_QUERY_THROW);
            OUString aUserLanguage = LanguageSelection::getLanguageString();
            Locale aLocale = LanguageSelection::IsoStringToLocale(aUserLanguage);
            localizable->setLocale(aLocale);

            Sequence< Any > theArgs(1);
            NamedValue v;
            v.Name = OUString::createFromAscii("NodePath");
            v.Value = makeAny(OUString::createFromAscii("org.openoffice.Setup"));
            theArgs[0] <<= v;
            Reference< XHierarchicalNameAccess> hnacc(
                theConfigProvider->createInstanceWithArguments(
                    sAccessSrvc, theArgs), UNO_QUERY_THROW);

            try
            {
                sal_Bool bValue = sal_False;
                hnacc->getByHierarchicalName(
                        OUString( RTL_CONSTASCII_USTRINGPARAM(
                            "Office/ooSetupInstCompleted" ) ) ) >>= bValue;

                return bValue ? true : false;
            }
            catch ( NoSuchElementException const & )
            {
                // just return false in this case.
            }
        }
        catch (Exception const & e)
        {
            OString msg(OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US));
            OSL_ENSURE(sal_False, msg.getStr());
        }

        return false;
    }

    UserInstall::UserInstallError UserInstall::finalize()
    {
        OUString aUserInstallPath;
        Bootstrap::PathStatus aLocateResult =
            Bootstrap::locateUserInstallation(aUserInstallPath);

        switch (aLocateResult) {

            case Bootstrap::DATA_INVALID:
            case Bootstrap::DATA_MISSING:
            case Bootstrap::DATA_UNKNOWN:
                // cannot find a valid path or path is missing
                return E_Unknown;

            case Bootstrap::PATH_EXISTS:
            {
                // path exists, check if an installation lives there
                if ( is_user_install() )
                {
                    return E_None;
                }
                // Note: fall-thru intended.
            }
            case Bootstrap::PATH_VALID:
                // found a path but need to create user install
                return create_user_install(aUserInstallPath);
            default:
                return E_Unknown;
        }
    }

    static osl::FileBase::RC copy_recursive( const rtl::OUString& srcUnqPath, const rtl::OUString& dstUnqPath)
    {

        FileBase::RC err;
        DirectoryItem aDirItem;
        DirectoryItem::get(srcUnqPath, aDirItem);
        FileStatus aFileStatus(FileStatusMask_All);
        aDirItem.getFileStatus(aFileStatus);

        if( aFileStatus.getFileType() == FileStatus::Directory)
        {
            // create directory if not already there
            err = Directory::create( dstUnqPath );
            if (err == osl::FileBase::E_EXIST)
                err = osl::FileBase::E_None;

            FileBase::RC next = err;
            if (err == osl::FileBase::E_None)
            {
                // iterate through directory contents
                Directory aDir( srcUnqPath );
                aDir.open();
                while (err ==  osl::FileBase::E_None &&
                    (next = aDir.getNextItem( aDirItem )) == osl::FileBase::E_None)
                {
                    aDirItem.getFileStatus(aFileStatus);
                    // generate new src/dst pair and make recursive call
                    rtl::OUString newSrcUnqPath = aFileStatus.getFileURL();
                    rtl::OUString newDstUnqPath = dstUnqPath;
                    rtl::OUString itemname = aFileStatus.getFileName();
                    // append trailing '/' if needed
                    if (newDstUnqPath.lastIndexOf(sal_Unicode('/')) != newDstUnqPath.getLength()-1)
                        newDstUnqPath += rtl::OUString::createFromAscii("/");
                    newDstUnqPath += itemname;
                    // recursion
                    err = copy_recursive(newSrcUnqPath, newDstUnqPath);
                }
                aDir.close();
                if( next != FileBase::E_NOENT ) err = FileBase::E_INVAL;
            }
        }
        else
        {
            // copy single file - foldback
            err = File::copy( srcUnqPath,dstUnqPath );
        }
        return err;
    }

    static const char *pszSrcList[] = {
        "/presets",
        NULL
    };
    static const char *pszDstList[] = {
        "/user",
        NULL
    };

    UserInstall::UserInstallError UserInstall::configureLanguage()
    {
        try
        {
            OUString sConfigSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
            OUString sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");

            // get configuration provider
            Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory();

            OUString aUserLanguage = LanguageSelection::getLanguageString();

            Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >(
                theMSF->createInstance(sConfigSrvc), UNO_QUERY_THROW);

            // localize the provider to user selection
            Reference< XLocalizable > localizable(theConfigProvider, UNO_QUERY_THROW);
            Locale aLocale = LanguageSelection::IsoStringToLocale(aUserLanguage);
            localizable->setLocale(aLocale);

            // org.openoffice.Setup/L10N/ooLocale
            // org.openoffice.Office.Linguistic/General/DefaultLocale
            // org.openoffice.Office.Linguistic/General/DefaultLocale_CJK

            Sequence< Any > theArgs(1);
            NamedValue v;
            v.Name = OUString::createFromAscii("NodePath");
            v.Value <<= OUString::createFromAscii("org.openoffice.Office.Linguistic/General");
            theArgs[0] <<= v;
            Reference< XPropertySet > pset = Reference< XPropertySet >(
                theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW);
            if (aUserLanguage.equalsAscii("ja") || aUserLanguage.equalsAscii("ko")
                || aUserLanguage.equalsAscii("zh-CN") || aUserLanguage.equalsAscii("zh-TW"))
            {
                pset->setPropertyValue(OUString::createFromAscii("DefaultLocale"), makeAny(OUString::createFromAscii("en-US")));
                pset->setPropertyValue(OUString::createFromAscii("DefaultLocale_CJK"), makeAny(aUserLanguage));
            } else
            {
                pset->setPropertyValue(OUString::createFromAscii("DefaultLocale"), makeAny(aUserLanguage));
            }
            Reference< XChangesBatch >(pset, UNO_QUERY_THROW)->commitChanges();

            v.Value = makeAny(OUString::createFromAscii("org.openoffice.Setup"));
            theArgs[0] <<= v;
            Reference< XHierarchicalPropertySet> hpset(
                theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW);
            hpset->setHierarchicalPropertyValue(OUString::createFromAscii("L10N/ooLocale"), makeAny(aUserLanguage));
            Reference< XChangesBatch >(hpset, UNO_QUERY_THROW)->commitChanges();

        } catch (Exception const & e)
        {
            OString msg(OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US));
            OSL_ENSURE(sal_False, msg.getStr());
            return UserInstall::E_Configuration;
        }

        // everything went well
        return UserInstall::E_None;
    }

    static UserInstall::UserInstallError create_user_install(OUString& aUserPath)
    {
        OUString aBasePath;
        if (Bootstrap::locateBaseInstallation(aBasePath) != Bootstrap::PATH_EXISTS)
            return UserInstall::E_InvalidBaseinstall;

        // create the user directory
        FileBase::RC rc = Directory::create(aUserPath);
        if ((rc != FileBase::E_None) && (rc != FileBase::E_EXIST)) return UserInstall::E_Creation;

            // copy data from shared data directory of base installation
        for (sal_Int32 i=0; pszSrcList[i]!=NULL && pszDstList[i]!=NULL; i++)
        {
            rc = copy_recursive(
                    aBasePath + OUString::createFromAscii(pszSrcList[i]),
                    aUserPath + OUString::createFromAscii(pszDstList[i]));
            if ((rc != FileBase::E_None) && (rc != FileBase::E_EXIST)) return UserInstall::E_Creation;
        }
        try
        {
            OUString sConfigSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationProvider");
            OUString sAccessSrvc = OUString::createFromAscii("com.sun.star.configuration.ConfigurationUpdateAccess");

            // get configuration provider
            Reference< XMultiServiceFactory > theMSF = comphelper::getProcessServiceFactory();
            Reference< XMultiServiceFactory > theConfigProvider = Reference< XMultiServiceFactory >(
                theMSF->createInstance(sConfigSrvc), UNO_QUERY_THROW);
            Sequence< Any > theArgs(1);
            NamedValue v(OUString::createFromAscii("NodePath"), makeAny(OUString::createFromAscii("org.openoffice.Setup")));
            //v.Name = OUString::createFromAscii("NodePath");
            //v.Value = makeAny(OUString::createFromAscii("org.openoffice.Setup"));
            theArgs[0] <<= v;
            Reference< XHierarchicalPropertySet> hpset(
                theConfigProvider->createInstanceWithArguments(sAccessSrvc, theArgs), UNO_QUERY_THROW);
            hpset->setHierarchicalPropertyValue(OUString::createFromAscii("Office/ooSetupInstCompleted"), makeAny(sal_True));
            Reference< XChangesBatch >(hpset, UNO_QUERY_THROW)->commitChanges();
        }
        catch (Exception& e)
        {
            OString aMsg("create_user_install(): ");
            aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US);
            OSL_ENSURE(sal_False, aMsg.getStr());
            return UserInstall::E_Creation;
        }

        return UserInstall::E_None;

    }
}
<|endoftext|>


<commit_before>// Filename: dcPackData.cxx
// Created by:  drose (15Jun04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

#include "dcPackData.h"

static const size_t extra_size = 50;

////////////////////////////////////////////////////////////////////
//     Function: DCPackData::set_used_length
//       Access: Private
//  Description: Ensures that the buffer has at least size bytes, and
//               sets the _used_length to the indicated values; grows
//               the buffer if it does not.
////////////////////////////////////////////////////////////////////
void DCPackData::
set_used_length(size_t size) {
  if (size > _allocated_size) {
    _allocated_size = size * size + extra_size;
    char *new_buf = new char[_allocated_size];
    if (_used_length > 0) {
      memcpy(new_buf, _buffer, _used_length);
    }
    if (_buffer != NULL) {
      delete[] _buffer;
    }
    _buffer = new_buf;
  }

  _used_length = size;
}
<commit_msg>changed comment<commit_after>// Filename: dcPackData.cxx
// Created by:  drose (15Jun04)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://etc.cmu.edu/panda3d/docs/license/ .
//
// To contact the maintainers of this program write to
// panda3d-general@lists.sourceforge.net .
//
////////////////////////////////////////////////////////////////////

#include "dcPackData.h"

static const size_t extra_size = 50;

////////////////////////////////////////////////////////////////////
//     Function: DCPackData::set_used_length
//       Access: Private
//  Description: Ensures that the buffer has at least size bytes, and
//               sets the _used_length to the indicated value; grows
//               the buffer if it does not.
////////////////////////////////////////////////////////////////////
void DCPackData::
set_used_length(size_t size) {
  if (size > _allocated_size) {
    _allocated_size = size * size + extra_size;
    char *new_buf = new char[_allocated_size];
    if (_used_length > 0) {
      memcpy(new_buf, _buffer, _used_length);
    }
    if (_buffer != NULL) {
      delete[] _buffer;
    }
    _buffer = new_buf;
  }

  _used_length = size;
}
<|endoftext|>


<commit_before>//
// ulib - a collection of useful classes
// Copyright (C) 2013-2014,2017 Michael Fink
//
/// \file MutexLock.hpp generic mutex lock classes
//
#pragma once

/// lock class for synchronisation objects
template <typename T>
class MutexLock
{
public:
   /// ctor; takes a lockable object
   MutexLock(T& mutex)
      :m_mutex(mutex)
   {
      mutex.Lock();
   }

   /// dtor; unlocks object
   ~MutexLock()
   {
      m_mutex.Unlock();
   }

private:
   MutexLock(const MutexLock&) = delete;              ///< removed copy ctor
   MutexLock& operator=(const MutexLock&) = delete;   ///< removed assign op

private:
   /// locked object
   T& m_mutex;
};

/// mutex lock class that initially doesn't lock mutex, and gives a method to try locking the mutex
template <typename T>
class MutexTryLock
{
public:
   /// ctor; takes a lockable object, but doesn't lock it yet
   MutexTryLock(T& mutex)
      :m_mutex(mutex)
   {
   }

   /// dtor; unlocks object
   ~MutexTryLock()
   {
      m_mutex.Unlock();
   }

   /// tries locking mutex until timeout (in milliseconds)
   bool Try(DWORD timeoutInMilliseconds)
   {
      return m_mutex.TryLock(timeoutInMilliseconds);
   }

private:
   MutexTryLock(const MutexTryLock&) = delete;              ///< removed copy ctor
   MutexTryLock& operator=(const MutexTryLock&) = delete;   ///< removed assign op

private:
   /// locked object
   T& m_mutex;
};

/// class for temporarily unlocking synchronisation objects
template <typename T>
class MutexUnLocker
{
public:
   /// ctor; takes a lockable object and unlocks it
   MutexUnLocker(T& mutex)
      :m_mutex(mutex)
   {
      mutex.Unlock();
   }

   /// dtor; locks object
   ~MutexUnLocker()
   {
      m_mutex.Lock();
   }

private:
   MutexUnLocker(const MutexUnLocker&) = delete;            ///< removed copy ctor
   MutexUnLocker& operator=(const MutexUnLocker&) = delete; ///< removed assign op

private:
   /// unlocked object
   T& m_mutex;
};
<commit_msg>made MutexLock, MutexTryLock and MutexUnLocker movable<commit_after>//
// ulib - a collection of useful classes
// Copyright (C) 2013-2014,2017,2019 Michael Fink
//
/// \file MutexLock.hpp generic mutex lock classes
//
#pragma once

/// lock class for synchronisation objects
template <typename T>
class MutexLock
{
public:
   /// ctor; takes a lockable object
   MutexLock(T& mutex)
      :m_mutex(mutex)
   {
      mutex.Lock();
   }

   /// dtor; unlocks object
   ~MutexLock()
   {
      m_mutex.Unlock();
   }

   /// move ctor; moves an already locked mutex to this object
   MutexLock(MutexLock&& lock)
      :m_mutex(std::move(lock.m_mutex))
   {
   }

   /// move assignment operator
   MutexLock& operator=(MutexLock&& lock)
   {
      m_mutex = std::move(lock.m_mutex);
   }

private:
   MutexLock(const MutexLock&) = delete;              ///< removed copy ctor
   MutexLock& operator=(const MutexLock&) = delete;   ///< removed assign op

private:
   /// locked object
   T& m_mutex;
};

/// mutex lock class that initially doesn't lock mutex, and gives a method to try locking the mutex
template <typename T>
class MutexTryLock
{
public:
   /// ctor; takes a lockable object, but doesn't lock it yet
   MutexTryLock(T& mutex)
      :m_mutex(mutex)
   {
   }

   /// dtor; unlocks object
   ~MutexTryLock()
   {
      m_mutex.Unlock();
   }

   /// move ctor; moves an already locked mutex to this object
   MutexTryLock(MutexTryLock&& lock)
      :m_mutex(std::move(lock.m_mutex))
   {
   }

   /// move assignment operator
   MutexTryLock& operator=(MutexTryLock&& lock)
   {
      m_mutex = std::move(lock.m_mutex);
   }

   /// tries locking mutex until timeout (in milliseconds)
   bool Try(DWORD timeoutInMilliseconds)
   {
      return m_mutex.TryLock(timeoutInMilliseconds);
   }

private:
   MutexTryLock(const MutexTryLock&) = delete;              ///< removed copy ctor
   MutexTryLock& operator=(const MutexTryLock&) = delete;   ///< removed assign op

private:
   /// locked object
   T& m_mutex;
};

/// class for temporarily unlocking synchronisation objects
template <typename T>
class MutexUnLocker
{
public:
   /// ctor; takes a lockable object and unlocks it
   MutexUnLocker(T& mutex)
      :m_mutex(mutex)
   {
      mutex.Unlock();
   }

   /// dtor; locks object
   ~MutexUnLocker()
   {
      m_mutex.Lock();
   }

   /// move ctor; moves an already locked mutex to this object
   MutexUnLocker(MutexUnLocker&& lock)
      :m_mutex(std::move(lock.m_mutex))
   {
   }

   /// move assignment operator
   MutexUnLocker& operator=(MutexUnLocker&& lock)
   {
      m_mutex = std::move(lock.m_mutex);
   }

private:
   MutexUnLocker(const MutexUnLocker&) = delete;            ///< removed copy ctor
   MutexUnLocker& operator=(const MutexUnLocker&) = delete; ///< removed assign op

private:
   /// unlocked object
   T& m_mutex;
};
<|endoftext|>