text:
#include "third_party/blink/renderer/core/css/font_face.h"

#include "base/metrics/histogram_macros.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_font_face_descriptors.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_string.h"
#include "third_party/blink/renderer/core/css/binary_data_font_face_source.h"
#include "third_party/blink/renderer/core/css/css_font_face.h"
#include "third_party/blink/renderer/core/css/css_font_face_src_value.h"
#include "third_party/blink/renderer/core/css/css_font_family_value.h"
#include "third_party/blink/renderer/core/css/css_font_selector.h"
#include "third_party/blink/renderer/core/css/css_font_style_range_value.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/css_unicode_range_value.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css/css_value_pair.h"
#include "third_party/blink/renderer/core/css/local_font_face_source.h"
#include "third_party/blink/renderer/core/css/offscreen_font_selector.h"
#include "third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/core/css/remote_font_face_source.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/css/style_rule.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/font_family_names.h"
#include "third_party/blink/renderer/platform/fonts/font_metrics_override.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"

namespace blink {

namespace {

const CSSValue* ParseCSSValue(const ExecutionContext* context,
                              const String& value,
                              AtRuleDescriptorID descriptor_id) {
  auto* window = DynamicTo<LocalDOMWindow>(context);
  CSSParserContext* parser_context =
      window ? MakeGarbageCollected<CSSParserContext>(*window->document())
             : MakeGarbageCollected<CSSParserContext>(*context);
  return AtRuleDescriptorParser::ParseFontFaceDescriptor(descriptor_id, value,
                                                         *parser_context);
}

CSSFontFace* CreateCSSFontFace(FontFace* font_face,
                               const CSSValue* unicode_range) {
  Vector<UnicodeRange> ranges;
  if (const auto* range_list = To<CSSValueList>(unicode_range)) {
    unsigned num_ranges = range_list->length();
    for (unsigned i = 0; i < num_ranges; i++) {
      const auto& range =
          To<cssvalue::CSSUnicodeRangeValue>(range_list->Item(i));
      ranges.push_back(UnicodeRange(range.From(), range.To()));
    }
  }

  return MakeGarbageCollected<CSSFontFace>(font_face, ranges);
}

const CSSValue* ConvertFontMetricOverrideValue(const CSSValue* parsed_value) {
  if (parsed_value && parsed_value->IsIdentifierValue()) {
    // We store the "normal" keyword value as nullptr
    DCHECK_EQ(CSSValueID::kNormal,
              To<CSSIdentifierValue>(parsed_value)->GetValueID());
    return nullptr;
  }
  return parsed_value;
}

const CSSValue* ConvertSizeAdjustValue(const CSSValue* parsed_value) {
  // We store the initial value 100% as nullptr
  if (parsed_value &&
      To<CSSPrimitiveValue>(parsed_value)->GetFloatValue() == 100.0f) {
    return nullptr;
  }
  return parsed_value;
}

}  // namespace

FontFace* FontFace::Create(
    ExecutionContext* execution_context,
    const AtomicString& family,
    const V8UnionArrayBufferOrArrayBufferViewOrString* source,
    const FontFaceDescriptors* descriptors) {
  DCHECK(source);

  switch (source->GetContentType()) {
    case V8UnionArrayBufferOrArrayBufferViewOrString::ContentType::kArrayBuffer:
      return Create(execution_context, family, source->GetAsArrayBuffer(),
                    descriptors);
    case V8UnionArrayBufferOrArrayBufferViewOrString::ContentType::
        kArrayBufferView:
      return Create(execution_context, family,
                    source->GetAsArrayBufferView().Get(), descriptors);
    case V8UnionArrayBufferOrArrayBufferViewOrString::ContentType::kString:
      return Create(execution_context, family, source->GetAsString(),
                    descriptors);
  }

  NOTREACHED();
  return nullptr;
}

FontFace* FontFace::Create(ExecutionContext* context,
                           const AtomicString& family,
                           const String& source,
                           const FontFaceDescriptors* descriptors) {
  FontFace* font_face =
      MakeGarbageCollected<FontFace>(context, family, descriptors);

  const CSSValue* src = ParseCSSValue(context, source, AtRuleDescriptorID::Src);
  if (!src || !src->IsValueList()) {
    font_face->SetError(MakeGarbageCollected<DOMException>(
        DOMExceptionCode::kSyntaxError,
        "The source provided ('" + source +
            "') could not be parsed as a value list."));
  }

  font_face->InitCSSFontFace(context, *src);
  return font_face;
}

FontFace* FontFace::Create(ExecutionContext* context,
                           const AtomicString& family,
                           DOMArrayBuffer* source,
                           const FontFaceDescriptors* descriptors) {
  FontFace* font_face =
      MakeGarbageCollected<FontFace>(context, family, descriptors);
  font_face->InitCSSFontFace(context,
                             static_cast<const unsigned char*>(source->Data()),
                             source->ByteLength());
  return font_face;
}

FontFace* FontFace::Create(ExecutionContext* context,
                           const AtomicString& family,
                           DOMArrayBufferView* source,
                           const FontFaceDescriptors* descriptors) {
  FontFace* font_face =
      MakeGarbageCollected<FontFace>(context, family, descriptors);
  font_face->InitCSSFontFace(
      context, static_cast<const unsigned char*>(source->BaseAddress()),
      source->byteLength());
  return font_face;
}

FontFace* FontFace::Create(Document* document,
                           const StyleRuleFontFace* font_face_rule,
                           bool is_user_style) {
  const CSSPropertyValueSet& properties = font_face_rule->Properties();

  // Obtain the font-family property and the src property. Both must be defined.
  auto* family = DynamicTo<CSSFontFamilyValue>(
      properties.GetPropertyCSSValue(AtRuleDescriptorID::FontFamily));
  if (!family)
    return nullptr;
  const CSSValue* src = properties.GetPropertyCSSValue(AtRuleDescriptorID::Src);
  if (!src || !src->IsValueList())
    return nullptr;

  FontFace* font_face = MakeGarbageCollected<FontFace>(
      document->GetExecutionContext(), font_face_rule, is_user_style);
  font_face->SetFamilyValue(*family);

  if (font_face->SetPropertyFromStyle(properties,
                                      AtRuleDescriptorID::FontStyle) &&
      font_face->SetPropertyFromStyle(properties,
                                      AtRuleDescriptorID::FontWeight) &&
      font_face->SetPropertyFromStyle(properties,
                                      AtRuleDescriptorID::FontStretch) &&
      font_face->SetPropertyFromStyle(properties,
                                      AtRuleDescriptorID::UnicodeRange) &&
      font_face->SetPropertyFromStyle(properties,
                                      AtRuleDescriptorID::FontVariant) &&
      font_face->SetPropertyFromStyle(
          properties, AtRuleDescriptorID::FontFeatureSettings) &&
      font_face->SetPropertyFromStyle(properties,
                                      AtRuleDescriptorID::FontDisplay) &&
      font_face->SetPropertyFromStyle(properties,
                                      AtRuleDescriptorID::AscentOverride) &&
      font_face->SetPropertyFromStyle(properties,
                                      AtRuleDescriptorID::DescentOverride) &&
      font_face->SetPropertyFromStyle(properties,
                                      AtRuleDescriptorID::LineGapOverride) &&
      font_face->SetPropertyFromStyle(properties,
                                      AtRuleDescriptorID::SizeAdjust) &&
      font_face->GetFontSelectionCapabilities().IsValid() &&
      !font_face->family().IsEmpty()) {
    font_face->InitCSSFontFace(document->GetExecutionContext(), *src);
    return font_face;
  }
  return nullptr;
}

FontFace::FontFace(ExecutionContext* context,
                   const StyleRuleFontFace* style_rule,
                   bool is_user_style)
    : ExecutionContextClient(context),
      status_(kUnloaded),
      style_rule_(style_rule),
      is_user_style_(is_user_style) {}

FontFace::FontFace(ExecutionContext* context,
                   const AtomicString& family,
                   const FontFaceDescriptors* descriptors)
    : ExecutionContextClient(context), family_(family), status_(kUnloaded) {
  SetPropertyFromString(context, descriptors->style(),
                        AtRuleDescriptorID::FontStyle);
  SetPropertyFromString(context, descriptors->weight(),
                        AtRuleDescriptorID::FontWeight);
  SetPropertyFromString(context, descriptors->stretch(),
                        AtRuleDescriptorID::FontStretch);
  SetPropertyFromString(context, descriptors->unicodeRange(),
                        AtRuleDescriptorID::UnicodeRange);
  SetPropertyFromString(context, descriptors->variant(),
                        AtRuleDescriptorID::FontVariant);
  SetPropertyFromString(context, descriptors->featureSettings(),
                        AtRuleDescriptorID::FontFeatureSettings);
  SetPropertyFromString(context, descriptors->display(),
                        AtRuleDescriptorID::FontDisplay);
  SetPropertyFromString(context, descriptors->ascentOverride(),
                        AtRuleDescriptorID::AscentOverride);
  SetPropertyFromString(context, descriptors->descentOverride(),
                        AtRuleDescriptorID::DescentOverride);
  SetPropertyFromString(context, descriptors->lineGapOverride(),
                        AtRuleDescriptorID::LineGapOverride);
  if (RuntimeEnabledFeatures::CSSFontFaceSizeAdjustEnabled()) {
    SetPropertyFromString(context, descriptors->sizeAdjust(),
                          AtRuleDescriptorID::SizeAdjust);
  }
}

FontFace::~FontFace() = default;

String FontFace::style() const {
  return style_ ? style_->CssText() : "normal";
}

String FontFace::weight() const {
  return weight_ ? weight_->CssText() : "normal";
}

String FontFace::stretch() const {
  return stretch_ ? stretch_->CssText() : "normal";
}

String FontFace::unicodeRange() const {
  return unicode_range_ ? unicode_range_->CssText() : "U+0-10FFFF";
}

String FontFace::variant() const {
  return variant_ ? variant_->CssText() : "normal";
}

String FontFace::featureSettings() const {
  return feature_settings_ ? feature_settings_->CssText() : "normal";
}

String FontFace::display() const {
  return display_ ? display_->CssText() : "auto";
}

String FontFace::ascentOverride() const {
  return ascent_override_ ? ascent_override_->CssText() : "normal";
}

String FontFace::descentOverride() const {
  return descent_override_ ? descent_override_->CssText() : "normal";
}

String FontFace::lineGapOverride() const {
  return line_gap_override_ ? line_gap_override_->CssText() : "normal";
}

String FontFace::sizeAdjust() const {
  return size_adjust_ ? size_adjust_->CssText() : "100%";
}

void FontFace::setStyle(ExecutionContext* context,
                        const String& s,
                        ExceptionState& exception_state) {
  SetPropertyFromString(context, s, AtRuleDescriptorID::FontStyle,
                        &exception_state);
}

void FontFace::setWeight(ExecutionContext* context,
                         const String& s,
                         ExceptionState& exception_state) {
  SetPropertyFromString(context, s, AtRuleDescriptorID::FontWeight,
                        &exception_state);
}

void FontFace::setStretch(ExecutionContext* context,
                          const String& s,
                          ExceptionState& exception_state) {
  SetPropertyFromString(context, s, AtRuleDescriptorID::FontStretch,
                        &exception_state);
}

void FontFace::setUnicodeRange(ExecutionContext* context,
                               const String& s,
                               ExceptionState& exception_state) {
  SetPropertyFromString(context, s, AtRuleDescriptorID::UnicodeRange,
                        &exception_state);
}

void FontFace::setVariant(ExecutionContext* context,
                          const String& s,
                          ExceptionState& exception_state) {
  SetPropertyFromString(context, s, AtRuleDescriptorID::FontVariant,
                        &exception_state);
}

void FontFace::setFeatureSettings(ExecutionContext* context,
                                  const String& s,
                                  ExceptionState& exception_state) {
  SetPropertyFromString(context, s, AtRuleDescriptorID::FontFeatureSettings,
                        &exception_state);
}

void FontFace::setDisplay(ExecutionContext* context,
                          const String& s,
                          ExceptionState& exception_state) {
  SetPropertyFromString(context, s, AtRuleDescriptorID::FontDisplay,
                        &exception_state);
}

void FontFace::setAscentOverride(ExecutionContext* context,
                                 const String& s,
                                 ExceptionState& exception_state) {
  SetPropertyFromString(context, s, AtRuleDescriptorID::AscentOverride,
                        &exception_state);
}

void FontFace::setDescentOverride(ExecutionContext* context,
                                  const String& s,
                                  ExceptionState& exception_state) {
  SetPropertyFromString(context, s, AtRuleDescriptorID::DescentOverride,
                        &exception_state);
}

void FontFace::setLineGapOverride(ExecutionContext* context,
                                  const String& s,
                                  ExceptionState& exception_state) {
  SetPropertyFromString(context, s, AtRuleDescriptorID::LineGapOverride,
                        &exception_state);
}

void FontFace::setSizeAdjust(ExecutionContext* context,
                             const String& s,
                             ExceptionState& exception_state) {
  SetPropertyFromString(context, s, AtRuleDescriptorID::SizeAdjust,
                        &exception_state);
}

void FontFace::SetPropertyFromString(const ExecutionContext* context,
                                     const String& s,
                                     AtRuleDescriptorID descriptor_id,
                                     ExceptionState* exception_state) {
  const CSSValue* value = ParseCSSValue(context, s, descriptor_id);
  if (value && SetPropertyValue(value, descriptor_id))
    return;

  String message = "Failed to set '" + s + "' as a property value.";
  if (exception_state) {
    exception_state->ThrowDOMException(DOMExceptionCode::kSyntaxError, message);
  } else {
    SetError(MakeGarbageCollected<DOMException>(DOMExceptionCode::kSyntaxError,
                                                message));
  }
}

bool FontFace::SetPropertyFromStyle(const CSSPropertyValueSet& properties,
                                    AtRuleDescriptorID property_id) {
  return SetPropertyValue(properties.GetPropertyCSSValue(property_id),
                          property_id);
}

bool FontFace::SetPropertyValue(const CSSValue* value,
                                AtRuleDescriptorID descriptor_id) {
  switch (descriptor_id) {
    case AtRuleDescriptorID::FontStyle:
      style_ = value;
      break;
    case AtRuleDescriptorID::FontWeight:
      weight_ = value;
      break;
    case AtRuleDescriptorID::FontStretch:
      stretch_ = value;
      break;
    case AtRuleDescriptorID::UnicodeRange:
      if (value && !value->IsValueList())
        return false;
      unicode_range_ = value;
      break;
    case AtRuleDescriptorID::FontVariant:
      variant_ = value;
      break;
    case AtRuleDescriptorID::FontFeatureSettings:
      feature_settings_ = value;
      break;
    case AtRuleDescriptorID::FontDisplay:
      display_ = value;
      if (css_font_face_)
        css_font_face_->SetDisplay(CSSValueToFontDisplay(display_.Get()));
      break;
    case AtRuleDescriptorID::AscentOverride:
      ascent_override_ = ConvertFontMetricOverrideValue(value);
      break;
    case AtRuleDescriptorID::DescentOverride:
      descent_override_ = ConvertFontMetricOverrideValue(value);
      break;
    case AtRuleDescriptorID::LineGapOverride:
      line_gap_override_ = ConvertFontMetricOverrideValue(value);
      break;
    case AtRuleDescriptorID::SizeAdjust:
      size_adjust_ = ConvertSizeAdjustValue(value);
      break;
    default:
      NOTREACHED();
      return false;
  }
  return true;
}

void FontFace::SetFamilyValue(const CSSFontFamilyValue& family_value) {
  family_ = family_value.Value();
}

String FontFace::status() const {
  switch (status_) {
    case kUnloaded:
      return "unloaded";
    case kLoading:
      return "loading";
    case kLoaded:
      return "loaded";
    case kError:
      return "error";
    default:
      NOTREACHED();
  }
  return g_empty_string;
}

void FontFace::SetLoadStatus(LoadStatusType status) {
  status_ = status;
  DCHECK(status_ != kError || error_);

  if (!GetExecutionContext())
    return;

  if (status_ == kLoaded || status_ == kError) {
    if (loaded_property_) {
      if (status_ == kLoaded) {
        GetExecutionContext()
            ->GetTaskRunner(TaskType::kDOMManipulation)
            ->PostTask(FROM_HERE,
                       WTF::Bind(&LoadedProperty::Resolve<FontFace*>,
                                 WrapPersistent(loaded_property_.Get()),
                                 WrapPersistent(this)));
      } else {
        GetExecutionContext()
            ->GetTaskRunner(TaskType::kDOMManipulation)
            ->PostTask(FROM_HERE,
                       WTF::Bind(&LoadedProperty::Reject<DOMException*>,
                                 WrapPersistent(loaded_property_.Get()),
                                 WrapPersistent(error_.Get())));
      }
    }

    GetExecutionContext()
        ->GetTaskRunner(TaskType::kDOMManipulation)
        ->PostTask(FROM_HERE,
                   WTF::Bind(&FontFace::RunCallbacks, WrapPersistent(this)));
  }
}

void FontFace::RunCallbacks() {
  HeapVector<Member<LoadFontCallback>> callbacks;
  callbacks_.swap(callbacks);
  for (wtf_size_t i = 0; i < callbacks.size(); ++i) {
    if (status_ == kLoaded)
      callbacks[i]->NotifyLoaded(this);
    else
      callbacks[i]->NotifyError(this);
  }
}

void FontFace::SetError(DOMException* error) {
  if (!error_) {
    error_ = error ? error
                   : MakeGarbageCollected<DOMException>(
                         DOMExceptionCode::kNetworkError);
  }
  SetLoadStatus(kError);
}

ScriptPromise FontFace::FontStatusPromise(ScriptState* script_state) {
  if (!loaded_property_) {
    loaded_property_ = MakeGarbageCollected<LoadedProperty>(
        ExecutionContext::From(script_state));
    if (status_ == kLoaded)
      loaded_property_->Resolve(this);
    else if (status_ == kError)
      loaded_property_->Reject(error_.Get());
  }
  return loaded_property_->Promise(script_state->World());
}

ScriptPromise FontFace::load(ScriptState* script_state) {
  if (status_ == kUnloaded)
    css_font_face_->Load();
  DidBeginImperativeLoad();
  return FontStatusPromise(script_state);
}

void FontFace::LoadWithCallback(LoadFontCallback* callback) {
  if (status_ == kUnloaded)
    css_font_face_->Load();
  AddCallback(callback);
}

void FontFace::AddCallback(LoadFontCallback* callback) {
  if (status_ == kLoaded)
    callback->NotifyLoaded(this);
  else if (status_ == kError)
    callback->NotifyError(this);
  else
    callbacks_.push_back(callback);
}

FontSelectionCapabilities FontFace::GetFontSelectionCapabilities() const {
  // FontSelectionCapabilities represents a range of available width, slope and
  // weight values. The first value of each pair is the minimum value, the
  // second is the maximum value.
  FontSelectionCapabilities normal_capabilities(
      {NormalWidthValue(), NormalWidthValue()},
      {NormalSlopeValue(), NormalSlopeValue()},
      {NormalWeightValue(), NormalWeightValue()});
  FontSelectionCapabilities capabilities(normal_capabilities);

  if (stretch_) {
    if (auto* stretch_identifier_value =
            DynamicTo<CSSIdentifierValue>(stretch_.Get())) {
      switch (stretch_identifier_value->GetValueID()) {
        case CSSValueID::kUltraCondensed:
          capabilities.width = {UltraCondensedWidthValue(),
                                UltraCondensedWidthValue(),
                                FontSelectionRange::RangeType::kSetExplicitly};
          break;
        case CSSValueID::kExtraCondensed:
          capabilities.width = {ExtraCondensedWidthValue(),
                                ExtraCondensedWidthValue(),
                                FontSelectionRange::RangeType::kSetExplicitly};
          break;
        case CSSValueID::kCondensed:
          capabilities.width = {CondensedWidthValue(), CondensedWidthValue(),
                                FontSelectionRange::RangeType::kSetExplicitly};
          break;
        case CSSValueID::kSemiCondensed:
          capabilities.width = {SemiCondensedWidthValue(),
                                SemiCondensedWidthValue(),
                                FontSelectionRange::RangeType::kSetExplicitly};
          break;
        case CSSValueID::kSemiExpanded:
          capabilities.width = {SemiExpandedWidthValue(),
                                SemiExpandedWidthValue(),
                                FontSelectionRange::RangeType::kSetExplicitly};
          break;
        case CSSValueID::kExpanded:
          capabilities.width = {ExpandedWidthValue(), ExpandedWidthValue(),
                                FontSelectionRange::RangeType::kSetExplicitly};
          break;
        case CSSValueID::kExtraExpanded:
          capabilities.width = {ExtraExpandedWidthValue(),
                                ExtraExpandedWidthValue(),
                                FontSelectionRange::RangeType::kSetExplicitly};
          break;
        case CSSValueID::kUltraExpanded:
          capabilities.width = {UltraExpandedWidthValue(),
                                UltraExpandedWidthValue(),
                                FontSelectionRange::RangeType::kSetExplicitly};
          break;
        case CSSValueID::kAuto:
          DCHECK(RuntimeEnabledFeatures::CSSFontFaceAutoVariableRangeEnabled());
          capabilities.width = {NormalWidthValue(), NormalWidthValue(),
                                FontSelectionRange::RangeType::kSetFromAuto};
          break;
        default:
          break;
      }
    } else if (const auto* stretch_list =
                   DynamicTo<CSSValueList>(stretch_.Get())) {
      // Transition FontFace interpretation of parsed values from
      // CSSIdentifierValue to CSSValueList or CSSPrimitiveValue.
      // TODO(drott) crbug.com/739139: Update the parser to only produce
      // CSSPrimitiveValue or CSSValueList.
      if (stretch_list->length() != 2)
        return normal_capabilities;
      const auto* stretch_from =
          DynamicTo<CSSPrimitiveValue>(&stretch_list->Item(0));
      const auto* stretch_to =
          DynamicTo<CSSPrimitiveValue>(&stretch_list->Item(1));
      if (!stretch_from || !stretch_to)
        return normal_capabilities;
      if (!stretch_from->IsPercentage() || !stretch_to->IsPercentage())
        return normal_capabilities;
      // https://drafts.csswg.org/css-fonts/#font-prop-desc
      // "User agents must swap the computed value of the startpoint and
      // endpoint of the range in order to forbid decreasing ranges."
      if (stretch_from->GetFloatValue() < stretch_to->GetFloatValue()) {
        capabilities.width = {FontSelectionValue(stretch_from->GetFloatValue()),
                              FontSelectionValue(stretch_to->GetFloatValue()),
                              FontSelectionRange::RangeType::kSetExplicitly};
      } else {
        capabilities.width = {FontSelectionValue(stretch_to->GetFloatValue()),
                              FontSelectionValue(stretch_from->GetFloatValue()),
                              FontSelectionRange::RangeType::kSetExplicitly};
      }
    } else if (auto* stretch_primitive_value =
                   DynamicTo<CSSPrimitiveValue>(stretch_.Get())) {
      float stretch_value = stretch_primitive_value->GetFloatValue();
      capabilities.width = {FontSelectionValue(stretch_value),
                            FontSelectionValue(stretch_value),
                            FontSelectionRange::RangeType::kSetExplicitly};
    } else {
      NOTREACHED();
      return normal_capabilities;
    }
  }

  if (style_) {
    if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(style_.Get())) {
      switch (identifier_value->GetValueID()) {
        case CSSValueID::kNormal:
          capabilities.slope = {NormalSlopeValue(), NormalSlopeValue(),
                                FontSelectionRange::RangeType::kSetExplicitly};
          break;
        case CSSValueID::kOblique:
          capabilities.slope = {ItalicSlopeValue(), ItalicSlopeValue(),
                                FontSelectionRange::RangeType::kSetExplicitly};
          break;
        case CSSValueID::kItalic:
          capabilities.slope = {ItalicSlopeValue(), ItalicSlopeValue(),
                                FontSelectionRange::RangeType::kSetExplicitly};
          break;
        case CSSValueID::kAuto:
          DCHECK(RuntimeEnabledFeatures::CSSFontFaceAutoVariableRangeEnabled());
          capabilities.slope = {NormalSlopeValue(), NormalSlopeValue(),
                                FontSelectionRange::RangeType::kSetFromAuto};
          break;
        default:
          break;
      }
    } else if (const auto* range_value =
                   DynamicTo<cssvalue::CSSFontStyleRangeValue>(style_.Get())) {
      if (range_value->GetFontStyleValue()->IsIdentifierValue()) {
        CSSValueID font_style_id =
            range_value->GetFontStyleValue()->GetValueID();
        if (!range_value->GetObliqueValues()) {
          if (font_style_id == CSSValueID::kNormal) {
            capabilities.slope = {
                NormalSlopeValue(), NormalSlopeValue(),
                FontSelectionRange::RangeType::kSetExplicitly};
          }
          DCHECK(font_style_id == CSSValueID::kItalic ||
                 font_style_id == CSSValueID::kOblique);
          capabilities.slope = {ItalicSlopeValue(), ItalicSlopeValue(),
                                FontSelectionRange::RangeType::kSetExplicitly};
        } else {
          DCHECK(font_style_id == CSSValueID::kOblique);
          size_t oblique_values_size =
              range_value->GetObliqueValues()->length();
          if (oblique_values_size == 1) {
            const auto& range_start =
                To<CSSPrimitiveValue>(range_value->GetObliqueValues()->Item(0));
            FontSelectionValue oblique_range(range_start.GetFloatValue());
            capabilities.slope = {
                oblique_range, oblique_range,
                FontSelectionRange::RangeType::kSetExplicitly};
          } else {
            DCHECK_EQ(oblique_values_size, 2u);
            const auto& range_start =
                To<CSSPrimitiveValue>(range_value->GetObliqueValues()->Item(0));
            const auto& range_end =
                To<CSSPrimitiveValue>(range_value->GetObliqueValues()->Item(1));
            // https://drafts.csswg.org/css-fonts/#font-prop-desc
            // "User agents must swap the computed value of the startpoint and
            // endpoint of the range in order to forbid decreasing ranges."
            if (range_start.GetFloatValue() < range_end.GetFloatValue()) {
              capabilities.slope = {
                  FontSelectionValue(range_start.GetFloatValue()),
                  FontSelectionValue(range_end.GetFloatValue()),
                  FontSelectionRange::RangeType::kSetExplicitly};
            } else {
              capabilities.slope = {
                  FontSelectionValue(range_end.GetFloatValue()),
                  FontSelectionValue(range_start.GetFloatValue()),
                  FontSelectionRange::RangeType::kSetExplicitly};
            }
          }
        }
      }
    } else {
      NOTREACHED();
      return normal_capabilities;
    }
  }

  if (weight_) {
    if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(weight_.Get())) {
      switch (identifier_value->GetValueID()) {
        // Although 'lighter' and 'bolder' are valid keywords for
        // font-weights, they are invalid inside font-face rules so they are
        // ignored. Reference:
        // http://www.w3.org/TR/css3-fonts/#descdef-font-weight.
        case CSSValueID::kLighter:
        case CSSValueID::kBolder:
          break;
        case CSSValueID::kNormal:
          capabilities.weight = {NormalWeightValue(), NormalWeightValue(),
                                 FontSelectionRange::RangeType::kSetExplicitly};
          break;
        case CSSValueID::kBold:
          capabilities.weight = {BoldWeightValue(), BoldWeightValue(),
                                 FontSelectionRange::RangeType::kSetExplicitly};
          break;
        case CSSValueID::kAuto:
          DCHECK(RuntimeEnabledFeatures::CSSFontFaceAutoVariableRangeEnabled());
          capabilities.weight = {NormalWeightValue(), NormalWeightValue(),
                                 FontSelectionRange::RangeType::kSetFromAuto};
          break;
        default:
          NOTREACHED();
          break;
      }
    } else if (const auto* weight_list =
                   DynamicTo<CSSValueList>(weight_.Get())) {
      if (weight_list->length() != 2)
        return normal_capabilities;
      const auto* weight_from =
          DynamicTo<CSSPrimitiveValue>(&weight_list->Item(0));
      const auto* weight_to =
          DynamicTo<CSSPrimitiveValue>(&weight_list->Item(1));
      if (!weight_from || !weight_to)
        return normal_capabilities;
      if (!weight_from->IsNumber() || !weight_to->IsNumber() ||
          weight_from->GetFloatValue() < 1 || weight_to->GetFloatValue() > 1000)
        return normal_capabilities;
      // https://drafts.csswg.org/css-fonts/#font-prop-desc
      // "User agents must swap the computed value of the startpoint and
      // endpoint of the range in order to forbid decreasing ranges."
      if (weight_from->GetFloatValue() < weight_to->GetFloatValue()) {
        capabilities.weight = {FontSelectionValue(weight_from->GetFloatValue()),
                               FontSelectionValue(weight_to->GetFloatValue()),
                               FontSelectionRange::RangeType::kSetExplicitly};
      } else {
        capabilities.weight = {FontSelectionValue(weight_to->GetFloatValue()),
                               FontSelectionValue(weight_from->GetFloatValue()),
                               FontSelectionRange::RangeType::kSetExplicitly};
      }
    } else if (auto* weight_primitive_value =
                   DynamicTo<CSSPrimitiveValue>(weight_.Get())) {
      float weight_value = weight_primitive_value->GetFloatValue();
      if (weight_value < 1 || weight_value > 1000)
        return normal_capabilities;
      capabilities.weight = {FontSelectionValue(weight_value),
                             FontSelectionValue(weight_value),
                             FontSelectionRange::RangeType::kSetExplicitly};
    } else {
      NOTREACHED();
      return normal_capabilities;
    }
  }

  return capabilities;
}

size_t FontFace::ApproximateBlankCharacterCount() const {
  if (status_ == kLoading)
    return css_font_face_->ApproximateBlankCharacterCount();
  return 0;
}

bool ContextAllowsDownload(ExecutionContext* context) {
  if (!context) {
    return false;
  }
  if (const auto* window = DynamicTo<LocalDOMWindow>(context)) {
    const Settings* settings =
        window->GetFrame() ? window->GetFrame()->GetSettings() : nullptr;
    return settings && settings->GetDownloadableBinaryFontsEnabled();
  }
  // TODO(fserb): ideally, we would like to have the settings value available
  // on workers. Right now, we don't support that.
  return true;
}

void FontFace::InitCSSFontFace(ExecutionContext* context, const CSSValue& src) {
  css_font_face_ = CreateCSSFontFace(this, unicode_range_.Get());
  if (error_)
    return;

  // Each item in the src property's list is a single CSSFontFaceSource. Put
  // them all into a CSSFontFace.
  const auto& src_list = To<CSSValueList>(src);
  int src_length = src_list.length();

  for (int i = 0; i < src_length; i++) {
    // An item in the list either specifies a string (local font name) or a URL
    // (remote font to download).
    const CSSFontFaceSrcValue& item = To<CSSFontFaceSrcValue>(src_list.Item(i));

    FontSelector* font_selector = nullptr;
    if (auto* window = DynamicTo<LocalDOMWindow>(context)) {
      font_selector = window->document()->GetStyleEngine().GetFontSelector();
    } else if (auto* scope = DynamicTo<WorkerGlobalScope>(context)) {
      font_selector = scope->GetFontSelector();
    } else {
      NOTREACHED();
    }
    if (!item.IsLocal()) {
      if (ContextAllowsDownload(context) && item.IsSupportedFormat()) {
        RemoteFontFaceSource* source =
            MakeGarbageCollected<RemoteFontFaceSource>(
                css_font_face_, font_selector,
                CSSValueToFontDisplay(display_.Get()));
        item.Fetch(context, source);
        css_font_face_->AddSource(source);
      }
    } else {
      css_font_face_->AddSource(MakeGarbageCollected<LocalFontFaceSource>(
          css_font_face_, font_selector, item.GetResource()));
    }
  }
}

void FontFace::InitCSSFontFace(ExecutionContext* context,
                               const unsigned char* data,
                               size_t size) {
  css_font_face_ = CreateCSSFontFace(this, unicode_range_.Get());
  if (error_)
    return;

  scoped_refptr<SharedBuffer> buffer = SharedBuffer::Create(data, size);
  BinaryDataFontFaceSource* source =
      MakeGarbageCollected<BinaryDataFontFaceSource>(
          css_font_face_, buffer.get(), ots_parse_message_);
  if (source->IsValid()) {
    SetLoadStatus(kLoaded);
  } else {
    if (!ots_parse_message_.IsEmpty()) {
      context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
          mojom::blink::ConsoleMessageSource::kOther,
          mojom::blink::ConsoleMessageLevel::kWarning,
          "OTS parsing error: " + ots_parse_message_));
    }
    SetError(MakeGarbageCollected<DOMException>(
        DOMExceptionCode::kSyntaxError, "Invalid font data in ArrayBuffer."));
  }
  css_font_face_->AddSource(source);
}

void FontFace::Trace(Visitor* visitor) const {
  visitor->Trace(style_);
  visitor->Trace(weight_);
  visitor->Trace(stretch_);
  visitor->Trace(unicode_range_);
  visitor->Trace(variant_);
  visitor->Trace(feature_settings_);
  visitor->Trace(display_);
  visitor->Trace(ascent_override_);
  visitor->Trace(descent_override_);
  visitor->Trace(line_gap_override_);
  visitor->Trace(advance_override_);
  visitor->Trace(size_adjust_);
  visitor->Trace(error_);
  visitor->Trace(loaded_property_);
  visitor->Trace(css_font_face_);
  visitor->Trace(callbacks_);
  visitor->Trace(style_rule_);
  ScriptWrappable::Trace(visitor);
  ExecutionContextClient::Trace(visitor);
}

bool FontFace::HadBlankText() const {
  return css_font_face_->HadBlankText();
}

bool FontFace::HasPendingActivity() const {
  return status_ == kLoading && GetExecutionContext();
}

FontDisplay FontFace::GetFontDisplay() const {
  return CSSValueToFontDisplay(display_.Get());
}

void FontFace::DidBeginImperativeLoad() {
  if (!DomWindow() ||
      !DomWindow()->document()->GetRenderBlockingResourceManager())
    return;
  DomWindow()
      ->document()
      ->GetRenderBlockingResourceManager()
      ->AddImperativeFontLoading(this);
}

FontMetricsOverride FontFace::GetFontMetricsOverride() const {
  FontMetricsOverride result;
  if (ascent_override_) {
    result.ascent_override =
        To<CSSPrimitiveValue>(*ascent_override_).GetFloatValue() / 100;
  }
  if (descent_override_) {
    result.descent_override =
        To<CSSPrimitiveValue>(*descent_override_).GetFloatValue() / 100;
  }
  if (line_gap_override_) {
    result.line_gap_override =
        To<CSSPrimitiveValue>(*line_gap_override_).GetFloatValue() / 100;
  }
  return result;
}

float FontFace::GetSizeAdjust() const {
  DCHECK(size_adjust_);
  return To<CSSPrimitiveValue>(*size_adjust_).GetFloatValue() / 100;
}

Document* FontFace::GetDocument() const {
  auto* window = DynamicTo<LocalDOMWindow>(GetExecutionContext());
  return window ? window->document() : nullptr;
}

}  // namespace blink


text:
4 Things You Should Do When You Owe People Money
You Basically NEED These 10 Store Products For ... Reasons
Sorry, But Ignoring Rose Tico Kind of Ruins 'Star Wars'
Felix Clay ·
Are you good with finances? Congratulations, you're an anomaly. The numbers say that more than 75 percent of American households carry some form of debt, and a good chunk of those carry over $50,000 in debt. That's a hell of a lot of money. In fact, according to Federal Reserve stats from May 2015, total credit card debt is at just over $90 billion. Billion! That's so much money that you could buy all the waffles ever.
Turns out, I am one of the many, and have royally screwed my finances -- specifically, with student loans. In fact, I recently received a most ominous letter requesting $25,000, with a less-than-implied "or else" tacked on to it. This prompted me to start my own Indiegogo campaign wherein I offer an abundance of fun perks to anyone willing to help me out with my monster debt. Donate $1 and I'll write you a 100-word story. Donate $20,000 and I'll get your portrait tattooed on my back, no word of a lie. Or there's more fun stuff in between. I'm dead serious and dead serious in debt, so I need help. Feel free to check out my campaign and offer assistance if you can!
My mistake doesn't have to be yours. Learn from my foolishness now to save yourself trouble later. Here's what I know about mismanaging money!
Give Your Money A Job
Noel Hendrickson/DigitalVision/Getty Images
Every dollar you possess should have a job. Don't let it just float around all willy-nilly like that breezy bag from American Beauty. The moment you have fun money is the money you hopped on a sled made of dipshittery barreling down a hill to ruin. No money is fun money, even if you spend it on fun things. That money should have been responsibly earmarked for entertainment.
Does it sound stupid to make yourself an entertainment fund and draw from it to go to movies, party with friends, buy yourself a kazoo? Maybe. But would you rather think you're a bit of a tool in your own head, since no one ever needs to know you do this, or wake up one day and realize you're so poor that you literally have less than a hobo? Just because you're in a house with a job doesn't make you better than a guy on a street corner. At least he's at ground zero. You're below it.
Thinkstock/Stockbyte/Getty Images
"Wait, he has multiple pairs of shoes? Shit."
If you don't respect your money -- how much you have now and how much you can expect tomorrow -- you're setting yourself up for doom. This is also known as "credit cards." They're awful things that we should have never invented. They're financial Balrogs, born from us digging too greedily and too deep into a mountain of eBay crap and Etsy brownies.
"YOU SHALL NOT PASS ... and especially not with a 400 score."
Every month, at least, you should plot your spending. Why? Because it offers perspective. If your money has no purpose and you order a pizza here, take a cab there, you might find yourself looking at your bank account with a $100 balance, wondering where that other $300 you swore you had went. And you'll look over your transactions and confirm that nope, you were never robbed. You kept spending little bits and little bits and little bits, until you buried yourself in a hole where you can choose to not spend any money for the next week or rely on credit. Boo!
If you're old enough to make money, you're likely in a place where you can determine how it needs to be spent. You need this much for rent, this much for your phone, this much for Internet, this much for groceries. Do this every time you get money, and then, when you have leftover money that isn't absolutely, positively needed for a specific expense every month, divvy it up between having fun and saving. But make sure it all has a purpose.
Photodisc/Photodisc/Getty Images
For example, this is my "buy a new jar" fund.
Have Goals
Ryan McVay/Photodisc/Getty Images
I said you should have savings, and that's a good idea, because you probably want a yacht or a flamingo. It's good, then, to have vague big-picture savings and clearer small-picture savings. Like, save in general for the sake of it, because who knows, maybe a trip to the moon will be affordable in 20 years. But save in specific if you really want that flamingo by next year. Don't just spend money because it's sitting around. If you put $100 in your savings, put $20 in the flamingo fund, just so it has that specific purpose.
Design Pics/Design Pics/Getty Images
Soon ...
If you don't have any goal or purpose to having money, you end up like me. Yeah, I have goals now, but I had to get kicked in the head a lot before my brain sorted itself out. One time in grad school, I had just gotten my latest student loan and used it to buy the books I needed, but of course I had extra money for things like food and not living in a dumpster. In my wisdom, I went out to a bar with my friends that night.
Now, this isn't necessarily bad. Like, as far as I've written it. It was bad for me, but it didn't have to be. That night, not only was I buying shots for all my friends; I actually recall (the night is very fuzzy in my memories -- warm and fuzzy) getting the shooter girl to sit with me and have shots. And I was tipping her for each shot. So she's getting paid to be at work, I'm paying to buy her drinks, and then tipping her to drink the drinks I paid for. And have no doubt, that girl loved me. For one evening, I was her best friend, and I was drunk enough to be convinced that I had suddenly become amazingly charming. Because she was hot. And sitting in my lap a lot. Because I gave her $400. In about two hours.
I could have gone to Safeway and bought enough bottles to open an actual bar in my living room.
I am dumb. I know that.
Your best bet for financial stability is to never do that. You can do that by knowing what your money is for. I can't stress that enough.
mactrunk/iStock/Getty Images
How significant are financial problems today? They're a major (if not the leading) cause of divorce. I found stats that kept contradicting one another, but all agreed that a hell of a lot of people, if not most, end up getting divorced not because of infidelity or foot fungus or lycanthropy, but because of financial problems. These things are often linked to a lack of communication; one partner doesn't talk to the other about what they need to save for or spend on, and they get nervous even broaching the subject. And if you've ever been in a serious relationship where you need to do financial shit together, this is often the case. If you're coming up short, you can often feel like your partner is scolding you like a child, or you feel guilty for not being able to cover things on your own, and one or both of you get resentful. This ends up being compounded if one person makes significantly more than the other, and you start thinking of your partner as wasting "your" money, even if you agreed that it's everyone's money.
"You think we can afford PBR? We're Natty Ice people until this kid is 18."
Money problems destroy relationships first and individuals second, but they don't have to. Never let your fear get the best of you. And this is hard, because collections people -- the ones who want all that money you can't pay -- are just ruthless shits. It's their job to threaten, cajole, strong-arm, and browbeat you into paying your debt. They don't give a shit if you can't work because raccoons ate your foot. Get a job as a pogo stick.
Yes, you still owe the money. And yes, the people you owe it to both want it now and have no interest in being your friend. But that doesn't mean things have to get ugly. Remember: Americans owe $90 billion, and that's just in credit card debt. The people you owe are used to being owed. They're going to be able to handle waiting for you to pay them back. They'll probably work out a deal with you as well, because in the face of that much debt, anyone willing to pay anything is kind of awesome. They won't tell you you're awesome -- they're stuck in their habit of being intimidating assholes -- but you are. They like people like you, and they need them. Without you, their lives are much harder. I mean, you could have paid your debt right off and avoided this altogether. But what are we, genies? We're working with what we have here.
Besides, genies don't have to pay rent.
When you try to work out a deal, they're going to want more than you want to pay, and that's where you're going to start panicking again. You might be able to spare $100 a month, and they might want $400 a week. So you negotiate, and if that fails (because these dudes can be obstinate), do yourself a favor and find a local nonprofit debt counselor. They can and will help mediate on your behalf, often getting you a much lower rate than you could on your own. That's good stuff. And maybe it will be more than that $100 a month, but you're going to have to make concessions.
LDProd/iStock/Getty Images
"They've requested that we shut down your Amazon Prime account
until it's clear that you can control your drunken self."
When you panic, you turn to things like avoidance. Do you know what avoidance gets you? When you just put your fingers in your ears and refuse to acknowledge that you have debt? You get to be me. You don't want that.
Keep Track Of Your Money
BernardaSv/iStock/Getty Images
It wasn't exactly like that for me; I didn't straight-up pretend that I had no debt. But I did some debt consolidation way back when, and got some amnesty on paying for a time, due to my financial situation. That was awesome. And as dumb as it sounds, as time went by, I actually forgot about my debt. I paid off credit card debts and other stuff that had happened more recently, and because the student debt was further in the past and had been back burnered, it wasn't a pressing issue. I literally forgot about it.
Every so often, I'd see a commercial about paying student loans, and I'd think, "Crap, I need to look into that." And then maybe the next commercial was for Taco Bell, and then I'd think, "Crap, I need a chalupa," and the loans were forgotten once more. And the sons of bitches literally never sent me any letters about it. I feel that was a mild failing on their part. Yes, I owe the money, and it's like 99 percent my responsibility, but come on. Give me a nudge. Clearly, I was irresponsible.
"As a courtesy, we now ask each customer if they remembered to pay their crippling loans."
You need to know what you owe, and to whom. Sounds entirely reasonable, but again, $90 billion. This is a huge issue for a lot of people. If this means literally writing it on a piece of paper and putting it on the fridge, then do it. Never let feeling silly be the reason you ruin your own life.
I genuinely don't want anyone falling into the same hole I did. And if you're between 18 and 23 or so right now, you're probably just not equipped to know how much damage it can do in the future. Some of you are. Some of you are smarter than I'll ever be. And that's good, but so many people stumble into these patterns of bad choices, bad spending, credit on top of credit, that it's devastating. The sooner you can look at money like a tool, like a finite resource you need to plot out and use with a strategy, the better. Lots of people do it. We should all be so wise and follow their example.
Scott Olson/Getty Images News/Getty Images
No. I said to use money as a tool, not to be a tool who uses money.
As for me, I'm absolutely in a bind. When I first started this campaign, I thought I'd just tell people I'm an affable goof. "I fucked up my loan repayment. I'm dumb. Please help me." But as a friend pointed out, if pride is an issue, then why am I asking for help at all? So to be completely honest, it's not just that I'm a financial disaster; it's that I am unable to manage all I took on. Years ago, my dad was in an accident at work. An elevator that carries supplies between floors at his workplace broke and fell, crushing his leg and almost taking his foot off. He was never able to work after that. Eventually my parents lost their house, and they now live in a co-op apartment, which is where the rent is reduced a bit with the agreement that the tenants do some simple property upkeep to offset that. My dad gardens.
For a while, I helped as much as I could, and my mom kept working. Unfortunately, she's too sick to work now, and was very recently diagnosed with multiple forms of cancer. And I'm just spread too thin. If you follow me on Twitter, you'll see me talking about new writing projects all the time. I write screenplays, I'm working on a novel, I do my work here, and I have a full-time job. But it's not enough. I can't do it, and it kills me to say it. I don't enjoy failure, and I enjoy admitting it even less. But again, if pride is an issue, why am I asking for help at all? Suck it up and just accept it. If I could have kept these loans at bay just a little longer, then who knows? Is my big break right around the corner? Am I the next big thing in screenwriting? As a novelist? I wish I knew. You have no idea how much I wish I knew. But I ran out of time, and it doesn't matter now. But like I said, I'm a comedy writer. I want to write or comedy my way out of this jam. My plan? Custom hilarity, just for you. If you donate even a single dollar to help me, I'll write you a 100-word short story. Check out the campaign, and see an example featuring Cracked's own Adam Tod Brown!
$10 will get you a custom 500-word story by me. You pick the genre!
$20 doubles up and I'll do a 1,000-word story. Your choice of genre!
$25 will get you an honest-to-goodness doodle made by me, with an accompanying backstory. Just look at this thing!
Is that drawn in mustard and ketchup? IT IS!
For $30, you get the super-coveted memento pack. What's in it? Two randomly chosen mementos from my life, and a story about how they made me the man I am today that may or may not be true. What sorts of mementos might they be? Look here!
Lube, anime, and a toothbrush chewed by a dog? Among other things?!?
For $50, not only will I write a 2,000-word story, but I'll also print it, sign it, and mail it to you. To your house!
For $75, you get the Felix Clay Surprise Pack. I can't tell you what's in it, or else the word "surprise" would be pointless. Suffice it to say that it's a magnificent risk that is guaranteed to be awesome.
$100 will get you your very own Cracked-style article on a topic of your choosing (so long as I don't find the topic too insane, awful, or obtuse). I may research it poorly, but I'll still write it, and it'll be one of a kind and all yours.
After $100 is when things get salty. $250 gets you that Cracked-style article, printed up pretty, all display quality and signed by me for your enjoyment.
$1,000 may be an insane amount of money, but I offer an insane perk. Your name will be tattooed on me. Literally. A fully real, permanent, rest-of-my-natural-life tattoo on my flesh.
ihorga/iStock/Getty Images
$5,000 is way over the top, so I have to up the ante. See those Tyrannocopters in my column header? You get to be tattooed, as a Tyrannocopter pilot, right on my flesh. Again, this is 100 percent real, no-joke stuff. I know a guy who will give me a deal on these tattoos because he thinks it's funny.
And the big one, the most insane thing of all: If someone can pony up $20,000, I will get their portrait tattooed on my back. Like a giant, full-back tattoo. The whole thing will be recorded and photographed as proof that it's real. I'm not playing here.
Whatever happens, I'm still writing comedy, and still appreciating the people willing to help me beyond words. I do what I do because I love it. I like making people laugh, and maybe being a bright spot in your day. That's not changing any time soon.
Debt collectors will hound you wherever you go. Heck, they'll attack you on social media. See what else they'll do in 5 Disturbing New Ways Debt Collectors Are Getting Your Money. And for more reasons why when it rains, YOU are poor (see what we did there?) check out 4 Legal Loopholes That Screw You When You're Poor.
Subscribe to our YouTube channel to see how being poor started in The Invention Of Homelessness, as well as watch other videos you won't see on the site!
Also follow us on Facebook because 4 out of 5 dentists recommend it. The 5th dentist is going through some hard times.
5 Weirdly Specific Movie Tropes That Are Suddenly Everywhere
How did these hyper-specific tropes spread so quickly?
By Jordan Breeding
Most rich kids just want to be pop stars.
By Alex Hanton
4 Dark Alternate Theories About Famous Hollywood Deaths
The Hollywood rumor mill has been playing games with celebrity deaths for at least a century.
By Andrew McRae
5 Modern Traditions That Are Stupid BS
It's weird how many traditions we've come up with in recent years kinda suck.
By Lydia Bugg
It's easy to work the system and win these awards even if you don't deserve them.
By Ryan Menezes
The 4 Most Annoying Trends In 'Prestige' TV Shows
After a while all these prestige TV shows start to look the same.
By Mac Faber

redpajama_set_name: RedPajamaCommonCrawl


Ed Laycox of West, Lane & Schlanger represented the seller, Hicone Properties, LLC in this transaction.
According to Dara Hewat of Black Oak, "After many months of work, we are happy to have completed our acquisition of the Hicone Shopping Center in Greensboro, North Carolina. Black Oak has a long history of owning and improving grocery-anchored centers similar to Hicone. We look forward to making future investments to support existing businesses operating at the center and to attract new ones that meet the everyday needs of the local community." This acquisition is the first in Black Oak Associates' latest investment funding vehicle, Black Oak IV. Black Oak assumed existing debt financing from John Hancock Life Insurance Company to complete the transaction.
With the acquisition of Hicone Shopping Center, Black Oak has purchased six grocery-anchored centers in the past two years, including the acquisitions of New Town Village, South Cumberland Marketplace, Hastings Marketplace, Laurel Gardens, and Unity Village Shoppes.
Black Oak Associates is a regional, private development company that specializes in creating retail and mixed-use projects with a focus on long term performance and efficiency driven sustainability. The firm focuses on shopping centers located in the Mid-Atlantic and South East regions. The company's portfolio currently includes fourteen shopping centers comprising approximately two million square feet.


Seared scallops with creamy cheese sauce keto recipe.
There is something about a seafood dish in light cream sauce.
The broth is rich in flavors without having to have too many things added to it.
This dish is the perfect example of seafood done right.
It's juicy, light, yet bold in flavors.
And if you love scallops, this can easily be your most favorite scallop recipe.
For this recipe, I use big scallops instead of baby ones. I also prefer working with fresh scallops over frozen ones. I find them juicier than frozen ones.
Scallops are one of my favorite seafood shellfish, and this recipe makes me love eating them even more. Try. I promise you'll love (:-) them too!
Pat the scallops dry and season it with salt and pepper. Chop the bacon into small bits.
Heat 1 tbsp butter in a medium pan over medium-high heat. Add the bacon and cook until crispy. Remove the bacon with a slotted spoon. Leave the bacon grease in the pan.
Turn the heat to high and add the scallops to the pan. Saute for 1-2 minutes per side until both sides are golden and cooked. Remove the scallops to a plate.
Add the bacon back to the pan and 1 tbsp of butter. Saute for one minute before adding the cream. Drop the heat down to medium and add the cream and cheese into the pan. Lower the heat to low and stir often until the sauce is thickened and reduced by half. The sauce should coat the back of a spoon.
Return the scallops to the pan and coat it with the sauce before serving.
Per Serving: 782 calories, 73 g fat, 24g protein, 11g total carbs, 10g net carbs.
You say in directions to add cream cheese did you mean whipping cream?


Ceanothus are California's wild lilac. A native evergreen shrub which is drought tolerant and spring time showy with lavender-blue 6" spikes. Belonging to the Rhamnaceae (Buckhorns) family, Ceanothus shrubs, in general are drought tolerant once established and are found frequently growing in California's native chaparral. There are many different varieties of Ceanothus in form and blooming lavender-blue colors. Ceanothus bloom winter to spring and are simply stunning. Three of my favorite Ceanothus are Ceanothus concha, Ceanothus dark star, and Ceanothus Ray Hartman.
Officially a shrub, Ceanothus Ray Harman variety has an upright tendency. It is one of the Ceanothus varieties that can be trained into a mature small tree, sometimes reaching up to 15' high and 10'-15" across. It does best in Zones 8-9.
In the above photo, my Ceanothus Ray Hartman is planted close to my soft-hued brown stucco wall for a pleasing backdrop. I planted four Ceanothus Ray Hartman in my garden a few years ago, and they grow quickly.
A few tips to share with you in creating a Ceanothus Ray Hartman tree in your garden. I purchased one-gallon size plants from the extraordinary California native nursery, Tree of Life Nursery. Tree of Life Nursery is located about 7 miles east of San Juan Capistrano on Ortega Highway. If you are serious about introducing more California natives in your yard and garden, Tree of Life Nursery is the place to go. Tree of Life Nursery offers over 20 varieties of ceanothus, as well as many other popular natives, and lesser known natives.
If your intention is to shape your Ceanothus Ray Hartman upright into a small tree, purchase Ceanothus Ray Hartman plants that have a nice single stem. Plant in a sunny spot with ample room. Water regularly to give it a good start, and then taper off once established. Prepare to support your Ceanothus Ray Hartman with stakes as it begins to grow and fill out.
Let your Ceanothus Ray Hartman grow and establish itself for a few years. After the second year, begin to trim bottom branches off of its main trunk slowly, at three month intervals. Nip or prune 6' off of the tips of some of your top branches and start shaping your tree. Trim as necessary to shape your tree into a nice upright tree form. This type of pruning encourages your Ceanothus Ray Hartman to grow upward and fill out into a beautiful wild lilac tree.
Please share if you are familar with the beauty of the Ceanothus varieties. Please comment if you have started introducing native plants into your garden.


text:
Q: Copy files from a list to a folder I have a text file abc.txt and its contents are:
   /lag/cnn/org/one.txt
   /lag/cnn/org/two.txt
   /lag/cnn/org/three.txt

If I use:
$ tar -cvf allfiles.tar -T abc.txt

I'm getting the tar of files in the list. Similarly is it possible to copy those files in abc.txt to a folder?
I tried this:
$ cp --files-from test1.txt ./Folder

But it is not working.

A: Note that the standard (POSIX/Unix) command to create a tar file is pax. pax combines the traditional cpio and tar commands.
To create a tar file, use the write mode:
pax -w < abc.txt > allfiles.tar

To copy instead, use the copy mode:
pax -rw < abc.txt Folder/

Note that it recreates the directory structure into Folder. If you want to flatten it, you could do:
pax -rws '|.*/||' < abc.txt Folder/

(see the man page if you want to copy permissions or other attributes as well. pax expects one file per line, which means files whose name contains newline characters cannot be copied that way, some pax implementations support a -0 option to allow a NUL delimited file list instead).
With cpio:
cpio -pd < abc.txt Folder/

With GNU tar:
tar -cf - -T abc.txt | (cd Folder && tar xf -)

Another option to allow any character in file names is (with GNU cp):
xargs cp -t Folder < abc.txt

(that flattens the directories).
xargs expects a blank (space, tab, newline) separated list, when you can escape those separators with backslash, single or double quotes. So you can have a list like:
"file with space"
other-file
'file with "quote" and
newline'

A: I'm not sure where you read that cp has a --files-from option, but I certainly don't have that using GNU coreutils 8.22.
As long as your filenames have no newlines in them, you can do this (with bash4+):
mapfile -t files < test1.txt
cp -- "${files[@]}" Folder/

If you don't have bash4+, then you can manually populate an array and use it (or just call cp directly from within read for each file, but that will be slower):
while IFS= read -r file; do
    files+=( "$file" )
done < test1.txt
cp -- "${files[@]}" Folder/

A: You can achieve this by a simple bash script:
for i in $(cat path_to_abc.txt)
do
  cp "$i" path_to_Folder
done

A safer way, that can deal with arbitrary file names:
while IFS= read -r file; do
    cp -- "$file" path_to_Folder
done

A: cp doesn't have a --files-from option (at least, GNU cp doesn't) but rsync does:
rsync --files-from abc.txt -av / Folder/

The / is used if your test.txt file contains files with absolute paths. Otherwise it should be the root of the source.
If your files are zero-terminated rather than newline-terminated you should include the --from0 option.

A: If you just want to copy the files with similar names you can use this :
Go to the source folder
cp $(ls  | grep 'one' | grep 'two') /tmp/

So all the files contains the string one and two in their names will be copied to tmp directory

redpajama_set_name: RedPajamaStackExchange


Blowout Sale! Up to 68% off on Slippers at CL Shoe Store, Page 5. Top brands include HomeTop, Git-up, LongBay, CIOR, ULTRAIDEAS, Wishcotton, OLUKAI, Onmygogo, ISOTONER, RockDove, Shevalues, Caramella Bubble, MEISUS, Fanture, FITORY, & MeKaren. Hurry! Limited time offers. Offers valid only while supplies last.


First of all, the last part of "Vampires Will Always Hurt You" is up over at naturallyxweird. 'Tis awesome.
And talking about awesomeness, I give you Andy Hurley!
I love how Patrick stalks off after a moment, like, "uh, okay then, I guess I'll leave too".
*sigh* I love these boys.


text:
A SEASON OF GREATNESS: A UAAP Season 80 Round-Up (Part 1)
 Home  badminton  basketball  beach volleyball  cheerdance  college sports  judo  swimming  table tennis  taekwondo  UAAP Season 80  A SEASON OF GREATNESS: A UAAP Season 80 Round-Up (Part 1)
Ateneo bannered Season 80 with a near-flawless run to the men's basketball crown. (Dennis Jerome Acosta / Dugout Philippines)
By Ricky Manliguis
As UAAP Season 80 draws to a close, let's look back at all the winning and record-breaking moments in all sporting disclipines, and witness how our UAAP student-athletes lived by the this year's theme of "Go For Great":
Basketball: Ateneo returns to winning ways, NU Lady Bulldogs still unscathed
Ateneo went back at the top of UAAP men's basketball supremacy after claiming the title at the expense of bitter rivals La Salle in three grueling games to end a near-perfect season.
After getting folied in its 14-0 bid in the elims, boys of former national team mentor Tab Baldwin got their payback in the finals against the Green Archers, and with series MVP Thirdy Ravena and Isaac Go firing, the Eagles pulled off an 88-86 win in Game 3.
The win was Ateneo's first since its five-peat drive from Seasons 71-75 under coach Norman Black.
National U, on the other hand, continued its dominance in the women's basketball competition, completing another flawless season capped off with a series sweep of Univeristy Of the East in the final. The girls of coach Patrick Aquino has already won 64 straight games, cementing themselves as the best women's basketball program in league history.
With season MVP Jack Animam at the forefront, NU continued its winning ways in the women's basketball competitions. (Dugout Philippines)
Badminton: NU snares 4-peat in men's play, La Salle foils UP in women's final
National University continued its dominance in the badminton courts, registering another perfect season for its fourth straight men's title at the Rizal Memorial badminton halls.
Bannered by tournament MVP Alvin Morada and Season 79 best shuttler Leeward Pedrosa, the
Bulldogs whitewashed University of the Philippines, 3-0, in the final for its 35th straight win and tying its victims with five titles.
In the distaff side, however, it was a different story as De La Salle pulled the rug from under three-peat champs UP in a thrilling finale, 3-2, with come-backing Nicole Albo providing the crucial win in the final singles match. The win is the Taft-based lady smashers' first since Season 72.
NU, UST dominate in Beach Volleyball
Over at the sands of MOA, National U and UST collared their respective titles in contrasting fashion.
With Bryan Bagunas leading the charge, the Bulldogs dethroned UST in the winner-take-all Game 3, 21-15, 14-21, 15-13, for the school's fourth beach volley win.
Sisi Rondina and Caitly Viray avenged their male conterparts in the women's gold medal match, disposing FEU tandem Bernadeth Pons and Kyle Atienza via sweep to successfully defend their title.
Table Tennis: La Salle notches 4th straight women's crown, NU spoils men's play
With their former captain on their minds, De La Salle continued its dominance in the women's table tennis competitions, bagging their fourth consecutive title, while National U shocked the rest of the field by snaring the men's title.
The Lady Archers, playing in their first year of the post Ian Lariba era, bucked a Game 1 loss to beat University of Santo Tomas, 2-1, in the final. The team later offered the victory to the Rio Olympian Lariba, who was diagnosed with Acute Myeloid Leukemia in May of last year.
NU snatched the men's crown, its first in the competition, stunning defending champions UST in the deciding third game.
Taekwondo: NU scores Kyorugi double, UST rules poomsae
NU ruled both the men's and women's kyorugi (combat) events, registering perfect seasons at the Blue Eagle Gym. The men's team swept all of its six assignments to claim the men's crown. The Lady Bulldogs then hacked out the golden double via similar 6-0 sweep, punctuated by a 5-2 win over UP.
UST meanwhile, banked on veterans Jocel Ninobla and Rodolfo Reyes Jr. en route to its third poomsae title for the España-based jins.
Swimming: Ateneo dominates with double championships
Ateneo stamped its class anew in both the men's and women's catergory at the Rizal Memorial swimming pools.
Bannered by two-time Olympian Jessie King Lacuna, the tankers from Katipunan accumulated 567 points to beat out La Salle and UP for its fourth straight men's tiltle and fifth over-all. DLSU was a distant second with 328 points, while Up had 191.
The Lady Eagles made it a double celebration with 328 points enough to dethorne UP and get back the crown it last won in Season 78.
UST and La Salle, meanwhile, both scored repeats in their respective juniors' competitions. The Growling Tigers kept its boys' plum while La Salle had the girls' version.
Judo: UST still growls
Another UST win came from judo, as it produced another golden double in the competitions at the De La Salle Zobel Sports Pavillion.
The men's team had to share the title with Ateneo after posting identical 30 points after the two-day festivities. The women's, team, on the other hand, annexed the women's crown with 45 total points, edging out closest pursuant University of the East.
The Golden Judokas now has 13 judo titles, while their women counterparts had their 10th crown.
After a podium finish a season ago, Adamson U finally nailed the cheerdance title (Denver Lachica / Dugout Philippines)
Cheerdance: Adamson U soars to championship with 80s theme
History was etched in the centerpiece cheerdance competitions as Adamson University collared its first-ever CDC win in front of a sell-out Mall Of Asia Arena crowd Dec. 7. Bringing in an "80s for 80" vibe, the dancers from San Marcelino grooved their way for a total of 663.50 points en route to bagging the P340,000 cash prize.
The win improved ADU's third-place finish last season. UST Salinggawi Dance Troupe returned to the podium, finishing 2nd place, while Univeristy of the East notched third. National U failed in their attempt for a record-tying fifth straight title as it placed tied for fourth with hosts Far Eastern U.
Follow him on Twitter: @Teaching_Hero
badminton basketball beach volleyball cheerdance college sports judo swimming table tennis taekwondo UAAP Season 80


For young women, a first gynecologic exam is a rite of passage. It can also be very frightening. We offer a gentle and easy first exam, with a tremendous amount of education about normal gynecology and sexuality.


text:
'Why Adeleke Can't Win Osun Rerun Election Even With Omisore's Support' – APC
September 26, 2018 'Why Adeleke Can't Win Osun Rerun Election Even With Omisore's Support' – APC2018-09-26T07:14:15+00:00 - Gossips - No Comment
The All Progressives Congress, APC, has declared that the Peoples Democratic Party, PDP and its candidate, Ademola Adeleke, would still lose the rerun of the governorship election in Osun even if they get the support of the Social Democratic Party, SDP candidate, Iyiola Omisore.
APC said the opposition party was battling to get Omisore's support because it was clear to them that Adeleke cannot win on the popular vote.
In a statement on Tuesday by the Director of Publicity, Research and Strategy of the APC in Osun State, Kunle Oyatomi, the party said Adeleke was the least educated and qualified candidate.
The statement reads, "They know that the PDP candidate, Senator Ademola Adeleke, can't win on the popular votes.
"First, he is the least educated and qualified candidate Osun has ever raised in its history of the political contest.
"The fraud that brought him to this level (manipulation of card readers and purchase of PVC of ill-informed voters) that we are now discussing him as a potential governor, marks us as essentially an illiterate and backward democracy."
TRAGEDY!! Nigerian Job Seeker Collapses, Dies In Kogi
The post 'Why Adeleke Can't Win Osun Rerun Election Even With Omisore's Support' – APC appeared first on Naijaloaded | Nigeria's Most Visited Music & Entertainment Website.
https://damiblog.com.ng/2018/09/26/why-adeleke-cant-win-osun-rerun-election-even-with-omisores-support-apc/https://damiblog.com.ng/wp-content/uploads/2018/09/Ademola-Adeleke-6.jpghttps://damiblog.com.ng/wp-content/uploads/2018/09/Ademola-Adeleke-6-150x150.jpg 2018-09-26T07:14:15+00:00 Owoyomi DamilolaGossips
The All Progressives Congress, APC, has declared that the Peoples Democratic Party, PDP and its candidate, Ademola Adeleke, would still lose the rerun of the governorship election in Osun even if they get the support of the Social Democratic Party, SDP candidate, Iyiola Omisore. APC said the opposition party was...
« REVEALED!! Man United Boss Jose Mourinho At War With His Best Players
BREAKING!! NLC Declares Indefinite Strike Over Minimum Wage »


Speechless Wednesday… It's like Wordless Wednesday, 'cept different.
And I discovered it at this site yesterday, where it's listed with the top tag of "Demerol".
Yeah… This whole "Mommy Blog" gig?
*I'm absolutely certain that this has nothing to do with Naked David Beckham. Because Naked David Beckham can do no wrong. At least not on this pornographically drug-filled mommy blog, that is.


text:
Q: Visual Studio Remote Debugging : how to keep the remote terminal window open at the end of execution? I am using Visual Studio Professional 2019 for C/C++ development, and have setup the Remote Windows Debugger by following these instructions. It works fine, but I would like a feature and I can't find how to activate it.
When debugging locally, the program is executed using the "Microsoft Visual Studio Debug Console", which allows to stay open while displaying the exit code at the end of execution :
<program>.exe (process 2020) exited with code 1.
To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops.
Press any key to close this window . . .

I would like to have the same behavior when debugging remotely, but on the remote computer the program is executed with the regular Command Prompt, which does not offer this feature. I couldn't find how to do it by googling it.
Is it at all possible to keep the remote terminal open at the end of execution ?
Thanks.

A: Did some tests, and it seems this is by design and there is no option to keep the remote terminal window open at the end of execution.
This maybe doesn't meet your requirements, but perhaps you can try to add this code line as a work around:
system("pause");


On 31 January 2018, participants of the MIPT Physical and Mathematical School "Absolute Future" visited the Veksler and Baldin Laboratory of High Energy Physics JINR. 35 students from Moscow, the Moscow region, Nizhny Novgorod, Novosibirsk, Perm, Ivanovo, Arkhangelsk, Irkutsk, Tyumen, St. Petersburg, and Shymkent became guests of the Institute.
VBLHEB Researcher D. Dryablov showed the students around the Laboratory. He delivered an introductory lecture on the NICA project and described the problems scientists plan to solve using the new accelerator complex. The guests had an opportunity to see the model of the future MPD detector and the Collider construction site from the roof of the legendary Synchrophasotron that has been a JINR symbol for over 60 years.
Later on, O.Kuchenko and D.Dryablov told about the synchrophasotron and introduced the VBLHEP operating facilities to the students, including the LU-20 linear accelerator, the new HILAC injector, and the superconducting accelerator Nuclotron.
At the end of the visit, O.Kazinova and A.Shemchuk described to the students main stages of the assembling and testing of superconducting magnets produced for the NICA complex.


BALLSTON SPA, N.Y. (AP) - A 58-year-old man has pleaded guilty to killing his wife during an argument inside their upstate New York home last spring.
Michael Norton pleaded guilty Thursday in a Saratoga County court in Ballston Spa to a second-degree murder charge in the slaying of Sherry Norton.
Authorities say the couple was arguing in their home in the town of Hadley last May 3 when Norton hit his wife in the head with a hatchet.
His plea agreement with prosecutors came as his trial was scheduled to start at the end of the month.
Norton will be sentenced in January to 20 years to life in prison.


text:
Q: Pull requests that should be automatically merged aren't getting merged I've got a weird situation on GitHub.
I've got MainRepo that's been forked by two developers - DevFork1 & DevFork2. Each of the forks has master and dev branches, which master being the branch into which they merge any changes from MainRepo while continuing development and merge changes from dev when they're ready to make a pull request.
Now, the situation is as follows. DevFork1.master is up-to-date with MainRepo.master. DevFork1.dev is merged to DevFork1.master (also tried rebasing). A pull request is made to merge DevFork1.master to MainRepo.master.
When this pull request is being made online on GitHub, the developer sees the message saying that the pull request can be merged automatically. However, just after the request is made, when the reviewer of MainRepo checks the pull request, it shows that the changes can't be merged automatically and a manual merge is required ...
No other changes or pull requests have been made in the interim. Can someone explain what's going on..?

A: It appears that this was a temporary problem in one of the enterprise releases. I was contacted by a GitHub representative and after updates to the enterprise version running on our repository servers, the problem has never recurred.


text:
Baldovský statek je ruina hospodářského komplexu a venkovského zámečku z 19. století. Lze jej nalézt za lesíkem u Baldovského návrší, v okrese Domažlice, zhruba 1 km severovýchodně  od husitského pomníku. Místní název pro objekt je též Horní Baldov.

Statek vlastnil známý chodský lékař i politik Antonín Steidl.
Původní dům s pozemkem patřil rodině Pachlových. V roce 1867 byl odkoupen Antonínem Steidlem a přestavěn v rustikálním ruském stylu. Celý pozemek obsahoval dvojzámeček s levým křídlem pro hosty (tzv. carské), pravé křídlo bylo obýváno majitelem a jeho rodinou. Dvůr byl tvořen dále i užitnými stavbami (stáje, chlévy, konírna, byty pro zaměstnance, velké stodoly apod.). Za stodolami se dříve nacházel také ovocný sad, zahrada s altánem a pramenem pitné vody.

Nejznámější vlastník objektu, Antonín Steidl, jej během svého života užíval jako bydlení pro rodinu a rozvoj vlastního hospodářství. Na velkostatku mj. hostil i význačné osoby české historie – pobýval zde například básník Jan Neruda, či známý dramatik Jaroslav Vrchlický.

Sám majitel nemovitosti byl respektovanou postavou chodského kraje – působil jako dvorní lékař ruského prince Nikolaje Alexandroviče, 30 let byl i okresním starostou a dlouho také vrcholným politikem. V roce 1891 mj. kandidoval proti T. G. Masarykovi v parlamentních volbách do rakouské říšské rady.

Začátkem 20. století byl statek prodán neznámému majiteli, po roce 1948 vyvlastněn a používán místním JZD. V rámci svérázné integrační politiky státu byl v 70. letech svěřen do péče a obývání romským přistěhovalcům ze Slovenska. Ti na velkostatku žili až do roku 2010.

Aktuálně je stavba opuštěná, obytné i hospodářské budovy dále chátrají – propadají se nosné krovy střech, bortí se zdivo.

Odkazy

Literatura

Externí odkazy

Zámky v okrese Domažlice
Hospodářské dvory v Plzeňském kraji
Stavby v Domažlicích
Postaveno v 19. století
Postaveno 1867

redpajama_set_name: RedPajamaWikipedia


Small – Medium food manufacturing.
Cold storage is essential to protect food and other items from harmful bacteria and reduce spoilage. The moisture and bacteria control EnviroChill offers gives you the peace of mind knowing that your coldroom and refrigeration systems will not be the cause of a bacterial infection.
EnviroChill offer you the best of the best with natural moisture control filters and now, introducing ChillSafe®.
ChillSafe is an Australian made, sustainable eco product for refrigeration hygiene. This multi award winning product gives business owners peace of mind in knowing that they have a cost saving solution to maintain their equipment and control bacteria and mould to improve food safety.
EnviroChill's natural filters provide an additional range of benefits across all forms commercial refrigeration. The proven moisture control properties in these filters assist with creating an odour free environment, improve WH&S, reduce food wastage, and improve energy efficiency to reduce your carbon footprint.
To arrange a time to have our experienced team carry out a FREE 18 point cold room health check to get your refrigeration in tip top shape, call EnviroChill today on 0415 168 729.


How many places are named Mikhaylovka?
There are 102 places in the world named Mikhaylovka!
There are 102 places called Mikhaylovka in the world.
There are 57 places named Mikhaylovka in Russian Federation.
There are 20 places named Mikhaylovka in Ukraine.
There are 10 places named Mikhaylovka in Kazakhstan.
There are 4 places named Mikhaylovka in Moldova.
There are 3 places named Mikhaylovka in Armenia.
There are 2 places named Mikhaylovka in Kyrgyzstan.
There are 2 places named Mikhaylovka in Georgia.
There are 2 places named Mikhaylovka in Belarus.
There is one place named Mikhaylovka in Uzbekistan.
There is one place named Mikhaylovka in Azerbaijan.
Places called Mikhaylovka in Russian Federation.
Places called Mikhaylovka in Ukraine.
Places called Mikhaylovka in Kazakhstan.
Places called Mikhaylovka in Moldova.
Places called Mikhaylovka in Armenia.
Places called Mikhaylovka in Kyrgyzstan.
Places called Mikhaylovka in Georgia.
Places called Mikhaylovka in Belarus.
Places called Mikhaylovka in Uzbekistan.
Places called Mikhaylovka in Azerbaijan.


Sign up here and we 'll show you how.
Choose product of your interest, tell us about your establishment, create your free account by signing up with us. Once you are in, our team of experts is always here to help you.
Increase outreach of your brand through premium video inventory across the globe on highly competitive CPM rates.
Increase your websites revenue simply by up to 200% with our innovative technology and highly compatible video ad formats.
Pixel Ads is a cross-screen, multi-channel online video advertising company, partnered with premium publishers all over the world, from all major verticals i.e. Fashion & Style, Health & Fitness, Cooking, Finance, News, etc.
Audience targeting by verticals, device, player size, etc.
Working with Pixel Ads is no doubt a fantastic experience. They allowed us to drive incrementally more sales while staying within our monthly budget for each campaign, and their focus on brand safe advertising has no doubt elevated our brand position in the market.
Our relationship with Pixel Ads is not yet long but we are really enjoying working with such a great team. They are highly cooperative and always ready for the challenge. Our sales is increasing steadily and our brand uplift as well.
Digital Marketing Head, Mediatrick Inc.
© 2018. Pixel Ads FZE.


Why wasn't I asked for ID at the polling station when I voted?
Can I refuse to be on the List of Electors?
How do I know if I am a Canadian citizen?
I didn't get a Voter Information Card in the mail.
What if my name or address is incorrect on the List of Electors?
Where is a person "ordinarily resident"?
Can I still vote if I'm not on the List of Electors?
If I have dual citizenship, in Canada and another country, can I vote and retain my dual citizenship?
Who can see the List of Electors?
How come my spouse has received a letter to update his information and I haven't received a letter, did you miss me?
I already advised Elections NB of my change of address and my Voter Information Card was still sent to the wrong address. I want my address fixed!
I moved. Can I update my information over the phone?
I received a letter in the mail from Elections NB asking me about being added to the New Brunswick Register of Electors. It had a pamphlet and a return envelope in it.
Is there a penalty for misuse of the List of Electors?
Why can't you add or correct my name on the List of Electors using information from my tax return?
Why is my name on the federal list and not on the NB list?
I voted for my federal MP, why am I not included on the Register of Electors?
Can people serving a sentence in a correctional facility/ jail / prison vote?
Q. Do I need ID to vote?
A. To vote in a federal election, you must now show identification to vote.
In NB, the electoral system is based on the honour system (your word of honour) i.e. we trust that you are who you say you are, if your name is already on the List of Electors.
When you arrive at the polling station, you are required to state your name and address to the poll worker so that they can find your name on the List of Electors.
An election officer or a scrutineer who works for a candidate may challenge your right to vote at the polling station if he feels you are not an eligible elector. If this occurs, you will have to take an oath before you may receive a ballot.
Q. Am I on the List of Electors?
A. Everyone who is on the Register of Electors will be listed, and will be mailed a Voter Information Card prior to the advance polls. If you voted in the last province wide election you should be on the list, but occasionally people are missed.
Contact your Returning Office or Elections NB to confirm if your name is listed properly. If it is, they can advise you where you can vote. When you do visit a polling location, tell the Polling Official your name and address and your name will be looked up.
If your name is not on the List of Electors, you will have to be added to the list before you may vote.
Q. Can I refuse to be on the List of Electors?
A. Yes, but you must be on the list in order to vote.
If you want your name taken off the list after voting, you must request this in writing to Elections NB in Fredericton.
Q. How do I know if I am a Canadian citizen?
A. An immigrant with "landed immigrant" or "permanent resident" status is not yet a Canadian citizen.
If you have been issued a Canadian passport or citizenship certificate, you are a Canadian citizen.
If you were born in Canada of parents who were Canadian citizens you are a citizen, but if you were born outside of Canada call Citizenship and Immigration (Citizenship office) if you have any questions. The toll free number is 1 888 242-2100.
Q. I didn't get a Voter Information Card in the mail.
A. You do not need a Voter Information Card to vote, although it makes it faster. If you did not receive a card, contact your Returning Office or Elections NB to confirm if your name is listed properly. If it is, they can advise you where you can vote. When you do visit a polling location, tell the Polling Official your name and address and your name will be looked up.
Q. What if my name or address is incorrect on the List of Electors?
A. To correct personal information during an election, an elector may contact the local Returning Office or Elections NB by telephone, and after satisfactorily proving their identity to the revision agent, may update their personal information. If the elector's name cannot be located at his or her current or former address in NB, the elector will have to be added to the List of Electors.
An elector may also complete an Application for Correction or Deletion form when they go to the polls to vote, and leave it with the election officers at their poll; their information will then be corrected at the returning office after polling day.
Q. Where is a person "ordinarily resident"?
If you have two residences, one where the rest of your family lives and one where you live part of the time for work or school reasons, the place where your family lives is your "ordinary residence".
A summer residence, used mainly from May to October, will not be considered an "ordinary residence" unless you have no other residence in the province.
Residents of nursing homes, special care homes, and extended care units of hospitals are usually considered "ordinarily resident" in those facilities.
Inmates in correctional facilities who were ordinarily resident in New Brunswick before their arrest or sentencing can vote by special ballot in the region in which they were living prior to their arrest, no matter where they are incarcerated.
f you are unsure where you are "ordinarily resident", call your Returning Office or Elections NB and we will help you sort it out.
Q. Who is ineligible to vote?
A. In a provincial election, only the Chief Electoral Officer for the province and the returning officer for each electoral district cannot normally vote. A returning officer can vote to break a tie (after a re-count).
In a municipal, school district, or regional health authority election, only the Municipal Electoral Officer for the province cannot vote.
Q. Can I still vote if I'm not on the List of Electors?
A. If your name is not on the List of Electors, you will have to be added to the list before you may vote.
Q. If I have dual citizenship, in Canada and another country, can I vote and retain my dual citizenship?
A. Voting doesn't affect your Canadian citizenship rights; check with the embassy or consulate for the other country of which you are a citizen to find out its rules. United States citizens' rights are not affected.
Q. Who can see the List of Electors?
A. Only election officials or candidates are allowed to see the list. If you believe someone not qualified to vote is on the list you can ask the Returning Officer to confirm if they are, but election officials cannot give the listed address of any voter to another person.
Candidates may obtain Lists of Electors during an election, and the lists may only be used for election purposes.
Between elections, Members of the Legislative Assembly and registered political parties get a copy of the list annually, to assist in contacting constituents.
Q. Can a Voters List be used for research or historical purposes?
A. Following provincial elections, the Lists of Electors used at the polling stations eventually become part of the provincial archives, and then are public documents available to researchers and historians. Details of this process are available from the Provincial Archives at (506) 453-2122.
Q. How come my spouse has received a letter to update his information and I haven't received a letter, did you miss me?
A. Have you currently moved to the address you're at?
Did you update your license or address at Service NB?
Did you agree to them when they asked you if you would like them to make your information available to Elections NB?
If you have moved to a new address, or are new to the province, you have to give permission for Service NB to send us your update of information when you are there. This is most likely why we have not mailed a letter.
Another reason would be that the person doesn't have a drivers license or the person has not visited Service NB to let them know about the update or change of address. That is most likely why we have not mailed a letter.
* We have not found a match using the name and previous address provided.
Q. I already advised Elections NB of my change of address and my Voter Information Card was still sent to the wrong address. I want my address fixed!
A. Sometimes the data entry workers make mistakes when information is updated. If your name can be found on the Registry of Electors, your information can be updated over the phone, and will be corrected for any other upcoming local and provincial elections in NB.
Q. I moved. Can I update my information over the phone?
A. Yes, if you have moved within New Brunswick.
If you have moved to NB from out of province, you must be added to the List of Electors.
To correct personal information during an election, an elector may contact the local Returning Office or Elections NB by telephone, and after satisfactorily proving their identity to the revision agent, may update their personal information. If the elector's name cannot be located at his or her current or former address in NB, the elector will have to be added to the List of Electors.
Q. I received a letter in the mail from Elections NB asking me about being added to the New Brunswick Register of Electors. It had a pamphlet and a return envelope in it.
A. Recently, Elections NB received your updated name and address information from Service New Brunswick. We did not find your name registered to vote in provincial or local electoral events when we tried to match your name with those on the Register of Electors. You may have moved more than once since we last updated our information, or possibly the information was typed wrong before being sent to us.
Before your name may be added to the Register of Electors, Elections NB must receive a signed certification that you meet the voter qualifications for New Brunswick.
* Return the form in the enclosed stamped envelope, or by fax.
When the certification is returned, the elector will be added to the Register of Electors immediately.
Q. Is there a penalty for misuse of the List of Electors?
A. Yes, there are substantial fines for misuse of a List of Electors.
Q. Why can't you add or correct my name on the List of Electors using information from my tax return?
A. When you allow your name and address from your tax return to be shared with Elections Canada, this does not send your name to Elections NB. The federal voter registry is different than the New Brunswick Register of Electors. Also, the federal and provincial voter qualifications are different.
Q. Why is my name on the federal list and not on the NB list?
A. The federal voter registry is different than the New Brunswick Register of Electors. Elections Canada periodically shares information with Elections NB, but in some cases we cannot update our list due to differences in the information. Because the federal and provincial voter qualifications are different, you may not automatically meet the voter qualifications for New Brunswick.
A. Yes, but they cannot be candidates in an election.
Q. Can people serving a sentence in a correctional facility/ jail / prison vote?
They must vote for the region in which they were ordinarily resident at the time of their sentencing. If they have no previous address, they vote in the region where the court from which they were sentenced is located.


text:
Elgin man killed by Buffalo Grove police after authorities say he 'advanced' at officers pointing 2 guns
Buffalo Grove police responded to Boxwood Lane and Ratcliffe Road just after midnight, Dec. 2, 2021 on a report of a man with a gun. The man, who police said had two handguns, was fatally shot by a Buffalo Grove police officer. (James T. Norman / Pioneer Press)
Two Buffalo Grove police officers are on leave after fatally shooting a man just after midnight Thursday, in what the police chief said is the first such officer-involving incident in the northwest suburban town.
Authorities identified the man as Brian Christopher Howard, 25, of Elgin, but he had recently been living with family in Buffalo Grove.
Buffalo Grove police Chief Steven Casstevens, in a conference outside the village police station Thursday, said a 911 call came in that day around 12:30 a.m. and the caller reported a person in a park near Radcliffe Road and Boxwood Lane with two guns.
Casstevens said the caller, who police believe to be Howard, said, "'There's a dude standing out there and he's all crazy.'"
After the emergency dispatcher asked who the person with the guns was, the caller said "'That would be me,'" Casstevens said.
"'The dude just popped off two rounds,'" Casstevens said, quoting the caller. "'This guy is dangerous.'"
The operator asked "at least seven times" for the man to put down his weapons, which the man refused to do, Casstevens said.
Two officers then arrived on the scene. They asked the man to drop his weapons, which he did not do, Casstevens said. The man, now identified as Howard, then began to advance on officers, firing both his weapons.
Casstevens said it is not yet known if he fired at the officers directly or into the air, but officers continued to give orders, and then eventually returned fire. One officer struck the man and the other also fired several rounds.
Officers then performed CPR on Howard until the ambulance arrived, but he succumbed to his injuries, Casstevens said.
"No officer ever wants to take the life of another person," the chief said at the news conference. "All our officers are trained in de-escalation and critical incident response and mental health first aid. That being said, officers are often placed in split-second decisions where they are forced to take action that unfortunately results in deadly force."
Officers found two loaded weapons at the scene, a 9mm semi-automatic handgun and a .45 caliber semi-automatic handgun.
Casstevens said at the news conference that the department had one interaction with Howard in the past, which was an impaired driving arrest in 2017.
The Cook County medical examiner's office is handling the autopsy in this case, officials said. Buffalo Grove spans both Lake and Cook counties.
Both officers from the shooting have been placed on paid administrative leave until the investigation is over, which Casstevens said is department policy. Although both officers were taken to a nearby hospital, per department protocol, the chief said, neither was injured in the event.
Casstevens said to his knowledge, the fatal shooting Thursday was the first officer-related one that had ever taken place in Buffalo Grove. He called the two responding officers "seasoned" and said he believes they did everything they were trained to do to avoid the fatal outcome. He said the officers' identities will be released later.
While Buffalo Grove police officers do not currently have body-worn cameras, Casstevens said there is dash-cam footage of the entire event from one of the squad cars. It is being reviewed, he said, but will not be released until later.
The shooting is being investigated by the Lake County Major Crime Task Force, Casstevens said.