summaryrefslogtreecommitdiffstats
path: root/gfx/2d/InlineTranslator.cpp
blob: 51b9dfa7462ab33357b76c794e84509208b3638f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "InlineTranslator.h"
#include "RecordedEventImpl.h"
#include "DrawEventRecorder.h"

#include "gfxContext.h"
#include "nsDeviceContext.h"
#include "mozilla/gfx/RecordingTypes.h"
#include "mozilla/UniquePtr.h"

using namespace mozilla::gfx;

namespace mozilla::gfx {

InlineTranslator::InlineTranslator() : mFontContext(nullptr) {}

InlineTranslator::InlineTranslator(DrawTarget* aDT, void* aFontContext)
    : mBaseDT(aDT), mFontContext(aFontContext) {}

bool InlineTranslator::TranslateRecording(char* aData, size_t aLen) {
  // an istream like class for reading from memory
  struct MemReader {
    MemReader(char* aData, size_t aLen) : mData(aData), mEnd(aData + aLen) {}
    void read(char* s, std::streamsize n) {
      if (n <= (mEnd - mData)) {
        memcpy(s, mData, n);
        mData += n;
      } else {
        // We've requested more data than is available
        // set the Reader into an eof state
        SetIsBad();
      }
    }
    bool eof() { return mData > mEnd; }
    bool good() { return !eof(); }
    void SetIsBad() { mData = mEnd + 1; }

    char* mData;
    char* mEnd;
  };
  MemReader reader(aData, aLen);

  uint32_t magicInt;
  ReadElement(reader, magicInt);
  if (magicInt != mozilla::gfx::kMagicInt) {
    mError = "Magic";
    return false;
  }

  uint16_t majorRevision;
  ReadElement(reader, majorRevision);
  if (majorRevision != kMajorRevision) {
    mError = "Major";
    return false;
  }

  uint16_t minorRevision;
  ReadElement(reader, minorRevision);
  if (minorRevision > kMinorRevision) {
    mError = "Minor";
    return false;
  }

  int32_t eventType;
  ReadElement(reader, eventType);
  while (reader.good()) {
    bool success = RecordedEvent::DoWithEvent(
        reader, static_cast<RecordedEvent::EventType>(eventType),
        [&](RecordedEvent* recordedEvent) -> bool {
          // Make sure that the whole event was read from the stream
          // successfully.
          if (!reader.good()) {
            mError = " READ";
            return false;
          }

          if (!recordedEvent->PlayEvent(this)) {
            mError = " PLAY";
            return false;
          }

          return true;
        });
    if (!success) {
      mError = RecordedEvent::GetEventName(
                   static_cast<RecordedEvent::EventType>(eventType)) +
               mError;
      return false;
    }

    ReadElement(reader, eventType);
  }

  return true;
}

already_AddRefed<DrawTarget> InlineTranslator::CreateDrawTarget(
    ReferencePtr aRefPtr, const gfx::IntSize& aSize,
    gfx::SurfaceFormat aFormat) {
  MOZ_ASSERT(mBaseDT, "mBaseDT has not been initialized.");

  RefPtr<DrawTarget> drawTarget = mBaseDT;
  AddDrawTarget(aRefPtr, drawTarget);
  return drawTarget.forget();
}

already_AddRefed<SourceSurface> InlineTranslator::LookupExternalSurface(
    uint64_t aKey) {
  if (mExternalSurfaces) {
    RefPtr<SourceSurface> surface = mExternalSurfaces->Get(aKey);
    if (surface) {
      return surface.forget();
    }
  }

  if (!mDependentSurfaces) {
    return nullptr;
  }

  RefPtr<RecordedDependentSurface> recordedSurface =
      mDependentSurfaces->Get(aKey);
  if (!recordedSurface) {
    return nullptr;
  }

  RefPtr<DrawTarget> newDT = GetReferenceDrawTarget()->CreateSimilarDrawTarget(
      recordedSurface->mSize, SurfaceFormat::B8G8R8A8);

  InlineTranslator translator(newDT, nullptr);
  translator.SetDependentSurfaces(mDependentSurfaces);
  if (!translator.TranslateRecording((char*)recordedSurface->mRecording.mData,
                                     recordedSurface->mRecording.mLen)) {
    return nullptr;
  }

  RefPtr<SourceSurface> snapshot = newDT->Snapshot();
  return snapshot.forget();
}

}  // namespace mozilla::gfx